script for number of session per user in ppp

hi,
For one scenario, it is necessary for users to have only 3 sessions for each username to connect to the VPN. To solve this problem, I have used the script in the UP section of the profile, but the script does not work properly, please help.

:local allowed 3;
:local scount 0;
:local nama “$user”;
:local sess [/ppp active find where name=$nama]
:local callerid [/ppp active get [find name=$nama] caller-id];
:log warning "PPP User ($nama) Logged in from $callerid ";
:foreach sessid in= $sess do={
:set scount ($scount + 1);
:if ($scount <= $allowed ) do={
:log warning “Session ($scount) find for User: ($nama) is ($sessid) Allowed!”;
} else={
/ppp active remove [find session-id=$sessid];
:log error “Session ($scount) find for User: ($nama) is ($sessid) not Allowed and disconnected!”;
}
}

If you wrap you code in bracket { } and cut/paste to terminal, you would have see what was wrong.
For debugging in terminal change :log warning to :put to see the output

This line is missing a $

:set scount ($scount + 1);

correct

:set $scount ($scount + 1)

No need for ; at end of each line, use tab in code and post it with code tags like this version that should work:

:local allowed 3
:local scount 0
:local nama "$user"
:local sess [/ppp active find where name=$nama]
:local callerid [/ppp active get [find name=$nama] caller-id]
:log warning "PPP User ($nama) Logged in from $callerid "
:foreach sessid in= $sess do={
	:set $scount ($scount + 1)
	:if ($scount <= $allowed ) do={
		:log warning "Session ($scount) find for User: ($nama) is ($sessid) Allowed!"
	} else={
		/ppp active remove [find session-id=$sessid]
		:log error "Session ($scount) find for User: ($nama) is ($sessid) not Allowed and disconnected!"
	}
}

Test version to debug in terminal. Change ass_test_user_name to a vpn user name

{
:local allowed 3
:local scount 0
:local nama "add_test_user_name"
:local sess [/ppp active find where name=$nama]
:local callerid [/ppp active get [find name=$nama] caller-id]
:put "PPP User ($nama) Logged in from $callerid "
:foreach sessid in= $sess do={
	:set $scount ($scount + 1)
	:if ($scount <= $allowed ) do={
	:put "Session ($scount) find for User: ($nama) is ($sessid) Allowed!"
	} else={
#	/ppp active remove [find session-id=$sessid]
	:put "Session ($scount) find for User: ($nama) is ($sessid) not Allowed and disconnected!"
	}
}
}

Edit
I see in ppp user session that you can set user login to only one or many. MT should add a number instead and you have not needed the script.

Hi @Jotne, @rextended,

What is the correct way to mofify the value of a variable?

In your example you put the following:

# This line is missing a $
:set scount ($scount + 1);
# correct
:set $scount ($scount + 1)

However, Rex does not put it:

:if ([:len $searchresult] > 0) do={
        :set if [get $searchresult on-interface]
        :set outstring "For bridge host table the $activeMAC is coming from $if"

Let me know…

BR.

:global, :local and :set do not want $,
if you want "set" something inside array like :set ($array->"item") "value" apparently you must use $ in front of variable,
but really at that point the "name" of the variable is "passed" from the function (...) and you use the $ because the variable is inside the function (->)

I can make mistakes too, RouterOS is quite forgiving with syntax errors,
but then sometimes things don't work as expected anymore when they fix some problem, or whatever...
better to write immediately with the correct syntax...

some error check for understand
{

added path for avoid multiple time same string

/ppp active

:local allowed  3
:local scount   0

removed useless quotes

:local nama     "$user"
:local nama     $user

removed path for avoid multiple time same string

:local sess     [/ppp active find where name=$nama]
:local sess     [find where name=$nama]

already $sess is [find where name=$nama], why call it again???

(also missing where on previous line)

not fixed now: this line potentially can do error if is present more than one ppp session with same name

:local callerid [get [/ppp active find name=$nama] caller-id]
:local callerid [get $sess caller-id]

removed useless end space

:log warning "PPP User ($nama) Logged in from $callerid "
:log warning "PPP User ($nama) Logged in from $callerid"

removed big error: space between = and variable

:foreach sessid in= $sess do={
:foreach sessid in=$sess do={

after :set, $ must not be used

    :set $scount ($scount + 1)
    :set scount ($scount + 1)

noerror: or put a space on both sides, or not on both sides.

    :if ($scount <= $allowed ) do={
    :if ($scount <= $allowed) do={

    :log warning "Session ($scount) find for User: ($nama) is ($sessid) Allowed!"
} else={

removed path for avoid multiple time same string

added missing where

    /ppp active remove [find session-id=$sessid]
    remove [find where session-id=$sessid]
    :log error "Session ($scount) find for User: ($nama) is ($sessid) not Allowed and disconnected!"
}

}

Heads up for the learning tutorial. :+1:

Good explanation!

BR.

Another free lesson about bug on script parser:

this do not work… as expected… (the comment say where for RouterOS is the error)

{
:local test do={:return $1}
:put "Hi!\r\nHi!"
:put [$test "Hi!\r\nHi!"]
#                   ^
# syntax error (line 4 column 20)
}

Solution: use ( ) !!!

{
:local test do={:return $1}
:put "Hi!\r\nHi!"
:put [$test ("Hi!\r\nHi!")]
}

can also be solved on this way, but on this mode do not evidence script parser errors…

{
:local test do={:return $1}
:local t2 "Hi!\r\nHi!"
:put $t2
:put [$test $t2]
}

Thank you for your reply and for pointing out the coding errors

Yes, only one session is possible, but for more than this, for example, 3 sessions, it is not possible. If there is, I did not find it.

Thanks for your advice
With a few corrections and changes, the problem was solved and the code works properly

{
/ppp active

:local allowed 3

:local scount 0

:local nama $user

:local sess  [find where name=$nama]

:foreach sessid in=$sess do={

	:local sid [get $sessid session-id]

	:set scount ($scount+1)

	:if ($scount<=$allowed ) do={ 

		:log warning "Session #$scount  for User: ($nama) & SessionID: #$sid Allowed!"

	} else={

		:log error "Session #$scount  for User: ($nama) & SessionID: #$sid not Allowed and disconnected!"

		remove [find where session-id=[get $sessid session-id]]

		}

	}

}

I put the final code here for others to use