Annotation of embedaddon/mpd/src/l2tp.c, revision 1.1.1.4
1.1 misho 1:
2: /*
3: * l2tp.c
4: *
5: * Written by Alexander Motin <mav@FreeBSD.org>
6: */
7:
8: #include "ppp.h"
9: #include "phys.h"
10: #include "mbuf.h"
11: #include "ngfunc.h"
12: #include "l2tp.h"
13: #include "l2tp_avp.h"
14: #include "l2tp_ctrl.h"
15: #include "log.h"
16: #include "util.h"
17:
18: #include <sys/types.h>
19: #ifdef NOLIBPDEL
20: #include "contrib/libpdel/util/ghash.h"
21: #else
22: #include <pdel/util/ghash.h>
23: #endif
24:
1.1.1.2 misho 25: #include <net/ethernet.h>
1.1 misho 26: #include <netgraph/ng_message.h>
27: #include <netgraph/ng_socket.h>
28: #include <netgraph/ng_ksocket.h>
29: #include <netgraph/ng_l2tp.h>
30: #include <netgraph.h>
1.1.1.3 misho 31: #include <fnmatch.h>
1.1 misho 32:
33: /*
34: * DEFINITIONS
35: */
36:
37: #define L2TP_MTU 1600
38: #define L2TP_MRU L2TP_MTU
39:
40: #define L2TP_PORT 1701
41:
42: #define L2TP_CALL_MIN_BPS 56000
43: #define L2TP_CALL_MAX_BPS 64000
44:
45: struct l2tp_server {
46: struct u_addr self_addr; /* self IP address */
47: in_port_t self_port; /* self port */
48: int refs;
49: int sock; /* server listen socket */
50: EventRef event; /* listen for data messages */
51: };
52:
53: struct l2tp_tun {
54: struct u_addr self_addr; /* self IP address */
55: struct u_addr peer_addr; /* peer IP address */
56: char peer_iface[IFNAMSIZ]; /* Peer iface */
57: u_char peer_mac_addr[6]; /* Peer MAC address */
58: in_port_t self_port; /* self port */
59: in_port_t peer_port; /* peer port */
60: u_char connected; /* control connection is connected */
61: u_char alive; /* control connection is not dying */
62: u_int active_sessions;/* number of calls in this sunnels */
63: struct ppp_l2tp_ctrl *ctrl; /* control connection for this tunnel */
64: };
65:
66: struct l2tpinfo {
67: struct {
68: struct u_addr self_addr; /* self IP address */
69: struct u_range peer_addr; /* Peer IP addresses allowed */
70: in_port_t self_port; /* self port */
71: in_port_t peer_port; /* Peer port required (or zero) */
72: struct optinfo options;
73: char callingnum[64]; /* L2TP phone number to use */
74: char callednum[64]; /* L2TP phone number to use */
75: char hostname[MAXHOSTNAMELEN]; /* L2TP local hostname */
76: char secret[64]; /* L2TP tunnel secret */
77: char *fqdn_peer_addr; /* FQDN Peer address */
1.1.1.3 misho 78: char *peer_mask; /* L2TP peer hostname mask */
1.1 misho 79: } conf;
80: u_char opened; /* L2TP opened by phys */
81: u_char incoming; /* Call is incoming vs. outgoing */
82: u_char outcall; /* incall or outcall */
83: u_char sync; /* sync or async call */
84: struct l2tp_server *server; /* server associated with link */
85: struct l2tp_tun *tun; /* tunnel associated with link */
86: struct ppp_l2tp_sess *sess; /* current session for this link */
87: char callingnum[64]; /* current L2TP phone number */
88: char callednum[64]; /* current L2TP phone number */
89: };
90: typedef struct l2tpinfo *L2tpInfo;
91:
92: /* Set menu options */
93: enum {
94: SET_SELFADDR,
95: SET_PEERADDR,
96: SET_CALLINGNUM,
97: SET_CALLEDNUM,
98: SET_HOSTNAME,
1.1.1.3 misho 99: SET_PEERMASK,
1.1 misho 100: SET_SECRET,
101: SET_ENABLE,
102: SET_DISABLE
103: };
104:
105: /* Binary options */
106: enum {
107: L2TP_CONF_OUTCALL, /* when originating, calls are "outgoing" */
108: L2TP_CONF_HIDDEN, /* enable AVP hidding */
109: L2TP_CONF_LENGTH, /* enable Length field in data packets */
110: L2TP_CONF_DATASEQ, /* enable sequence fields in data packets */
111: L2TP_CONF_RESOLVE_ONCE /* Only once resolve peer_addr */
112: };
113:
114: /*
115: * INTERNAL FUNCTIONS
116: */
117:
118: static int L2tpTInit(void);
119: static void L2tpTShutdown(void);
120: static int L2tpInit(Link l);
121: static int L2tpInst(Link l, Link lt);
122: static void L2tpOpen(Link l);
123: static void L2tpClose(Link l);
124: static void L2tpShutdown(Link l);
125: static void L2tpStat(Context ctx);
126: static int L2tpOriginated(Link l);
127: static int L2tpIsSync(Link l);
128: static int L2tpSetAccm(Link l, u_int32_t xmit, u_int32_t recv);
129: static int L2tpSelfName(Link l, void *buf, size_t buf_len);
130: static int L2tpPeerName(Link l, void *buf, size_t buf_len);
131: static int L2tpSelfAddr(Link l, void *buf, size_t buf_len);
132: static int L2tpPeerAddr(Link l, void *buf, size_t buf_len);
133: static int L2tpPeerPort(Link l, void *buf, size_t buf_len);
134: static int L2tpPeerMacAddr(Link l, void *buf, size_t buf_len);
135: static int L2tpPeerIface(Link l, void *buf, size_t buf_len);
136: static int L2tpCallingNum(Link l, void *buf, size_t buf_len);
137: static int L2tpCalledNum(Link l, void *buf, size_t buf_len);
138: static int L2tpSetCallingNum(Link l, void *buf);
139: static int L2tpSetCalledNum(Link l, void *buf);
140:
141: static void L2tpHookUp(Link l);
142: static void L2tpUnhook(Link l);
143:
144: static void L2tpNodeUpdate(Link l);
145: static int L2tpListen(Link l);
146: static void L2tpUnListen(Link l);
1.1.1.4 ! misho 147: static int L2tpSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 148:
149: /* L2TP control callbacks */
150: static ppp_l2tp_ctrl_connected_t ppp_l2tp_ctrl_connected_cb;
151: static ppp_l2tp_ctrl_terminated_t ppp_l2tp_ctrl_terminated_cb;
152: static ppp_l2tp_ctrl_destroyed_t ppp_l2tp_ctrl_destroyed_cb;
153: static ppp_l2tp_initiated_t ppp_l2tp_initiated_cb;
154: static ppp_l2tp_connected_t ppp_l2tp_connected_cb;
155: static ppp_l2tp_terminated_t ppp_l2tp_terminated_cb;
156: static ppp_l2tp_set_link_info_t ppp_l2tp_set_link_info_cb;
157:
158: static const struct ppp_l2tp_ctrl_cb ppp_l2tp_server_ctrl_cb = {
159: ppp_l2tp_ctrl_connected_cb,
160: ppp_l2tp_ctrl_terminated_cb,
161: ppp_l2tp_ctrl_destroyed_cb,
162: ppp_l2tp_initiated_cb,
163: ppp_l2tp_connected_cb,
164: ppp_l2tp_terminated_cb,
165: ppp_l2tp_set_link_info_cb,
166: NULL,
167: };
168:
169: /*
170: * GLOBAL VARIABLES
171: */
172:
173: const struct phystype gL2tpPhysType = {
174: .name = "l2tp",
175: .descr = "Layer Two Tunneling Protocol",
176: .mtu = L2TP_MTU,
177: .mru = L2TP_MRU,
178: .tmpl = 1,
179: .tinit = L2tpTInit,
180: .tshutdown = L2tpTShutdown,
181: .init = L2tpInit,
182: .inst = L2tpInst,
183: .open = L2tpOpen,
184: .close = L2tpClose,
185: .update = L2tpNodeUpdate,
186: .shutdown = L2tpShutdown,
187: .showstat = L2tpStat,
188: .originate = L2tpOriginated,
189: .issync = L2tpIsSync,
190: .setaccm = L2tpSetAccm,
191: .setcallingnum = L2tpSetCallingNum,
192: .setcallednum = L2tpSetCalledNum,
193: .selfname = L2tpSelfName,
194: .peername = L2tpPeerName,
195: .selfaddr = L2tpSelfAddr,
196: .peeraddr = L2tpPeerAddr,
197: .peerport = L2tpPeerPort,
198: .peermacaddr = L2tpPeerMacAddr,
199: .peeriface = L2tpPeerIface,
200: .callingnum = L2tpCallingNum,
201: .callednum = L2tpCalledNum,
202: };
203:
204: const struct cmdtab L2tpSetCmds[] = {
205: { "self {ip} [{port}]", "Set local IP address",
206: L2tpSetCommand, NULL, 2, (void *) SET_SELFADDR },
207: { "peer {ip} [{port}]", "Set remote IP address",
208: L2tpSetCommand, NULL, 2, (void *) SET_PEERADDR },
209: { "callingnum {number}", "Set calling L2TP telephone number",
210: L2tpSetCommand, NULL, 2, (void *) SET_CALLINGNUM },
211: { "callednum {number}", "Set called L2TP telephone number",
212: L2tpSetCommand, NULL, 2, (void *) SET_CALLEDNUM },
213: { "hostname {name}", "Set L2TP local hostname",
214: L2tpSetCommand, NULL, 2, (void *) SET_HOSTNAME },
1.1.1.3 misho 215: { "pmask {mask}", "Set L2TP peer hostname mask",
216: L2tpSetCommand, NULL, 2, (void *) SET_PEERMASK },
1.1 misho 217: { "secret {sec}", "Set L2TP tunnel secret",
218: L2tpSetCommand, NULL, 2, (void *) SET_SECRET },
219: { "enable [opt ...]", "Enable option",
220: L2tpSetCommand, NULL, 2, (void *) SET_ENABLE },
221: { "disable [opt ...]", "Disable option",
222: L2tpSetCommand, NULL, 2, (void *) SET_DISABLE },
1.1.1.4 ! misho 223: { NULL, NULL, NULL, NULL, 0, NULL },
1.1 misho 224: };
225:
226: /*
227: * INTERNAL VARIABLES
228: */
229:
1.1.1.4 ! misho 230: static const struct confinfo gConfList[] = {
1.1 misho 231: { 0, L2TP_CONF_OUTCALL, "outcall" },
232: { 0, L2TP_CONF_HIDDEN, "hidden" },
233: { 0, L2TP_CONF_LENGTH, "length" },
234: { 0, L2TP_CONF_DATASEQ, "dataseq" },
235: { 0, L2TP_CONF_RESOLVE_ONCE, "resolve-once" },
236: { 0, 0, NULL },
237: };
238:
1.1.1.4 ! misho 239: static struct ghash *gL2tpServers;
! 240: static struct ghash *gL2tpTuns;
! 241: static int one = 1;
1.1 misho 242:
243: /*
244: * L2tpTInit()
245: */
246:
247: static int
248: L2tpTInit(void)
249: {
250: if ((gL2tpServers = ghash_create(NULL, 0, 0, MB_PHYS, NULL, NULL, NULL, NULL))
251: == NULL)
252: return(-1);
253: if ((gL2tpTuns = ghash_create(NULL, 0, 0, MB_PHYS, NULL, NULL, NULL, NULL))
254: == NULL)
255: return(-1);
256: return(0);
257: }
258:
259: /*
260: * L2tpTShutdown()
261: */
262:
263: static void
264: L2tpTShutdown(void)
265: {
266: struct ghash_walk walk;
267: struct l2tp_tun *tun;
268:
269: Log(LG_PHYS2, ("L2TP: Total shutdown"));
270: ghash_walk_init(gL2tpTuns, &walk);
271: while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
272: if (tun->ctrl) {
273: if (tun->alive)
274: ppp_l2tp_ctrl_shutdown(tun->ctrl,
275: L2TP_RESULT_SHUTDOWN, 0, NULL);
276: ppp_l2tp_ctrl_destroy(&tun->ctrl);
277: }
278: }
279: ghash_destroy(&gL2tpServers);
280: ghash_destroy(&gL2tpTuns);
281: }
282:
283: /*
284: * L2tpInit()
285: */
286:
287: static int
288: L2tpInit(Link l)
289: {
290: L2tpInfo l2tp;
291:
292: /* Initialize this link */
293: l2tp = (L2tpInfo) (l->info = Malloc(MB_PHYS, sizeof(*l2tp)));
294:
295: u_addrclear(&l2tp->conf.self_addr);
296: l2tp->conf.self_addr.family = AF_INET;
297: l2tp->conf.self_port = 0;
298: u_rangeclear(&l2tp->conf.peer_addr);
299: l2tp->conf.peer_addr.addr.family = AF_INET;
300: l2tp->conf.peer_addr.width = 0;
301: l2tp->conf.peer_port = 0;
302: l2tp->conf.fqdn_peer_addr = NULL;
1.1.1.3 misho 303: l2tp->conf.peer_mask = NULL;
1.1 misho 304:
305: Enable(&l2tp->conf.options, L2TP_CONF_DATASEQ);
306: Enable(&l2tp->conf.options, L2TP_CONF_RESOLVE_ONCE);
307:
308: return(0);
309: }
310:
311: /*
312: * L2tpInst()
313: */
314:
315: static int
316: L2tpInst(Link l, Link lt)
317: {
318: L2tpInfo pi;
319: L2tpInfo const pit = (L2tpInfo) lt->info;
320:
321: /* Initialize this link */
322: pi = (L2tpInfo) (l->info = Mdup(MB_PHYS, lt->info, sizeof(*pit)));
323: if (pit->conf.fqdn_peer_addr != NULL)
324: pi->conf.fqdn_peer_addr =
325: Mstrdup(MB_PHYS, pit->conf.fqdn_peer_addr);
1.1.1.3 misho 326: if (pit->conf.peer_mask != NULL)
327: pi->conf.peer_mask = Mstrdup(MB_PHYS, pit->conf.peer_mask);
1.1 misho 328: if (pi->server)
329: pi->server->refs++;
330:
331: return(0);
332: }
333:
334: /*
335: * L2tpOpen()
336: */
337:
338: static void
339: L2tpOpen(Link l)
340: {
341: L2tpInfo const pi = (L2tpInfo) l->info;
342:
343: struct l2tp_tun *tun = NULL;
344: struct ppp_l2tp_sess *sess;
345: struct ppp_l2tp_avp_list *avps = NULL;
346: union {
347: u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
348: struct ng_ksocket_sockopt sockopt;
349: } sockopt_buf;
350: struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
351: union {
352: u_char buf[sizeof(struct ng_mesg) + sizeof(struct sockaddr_storage)];
353: struct ng_mesg reply;
354: } ugetsas;
355: struct sockaddr_storage *const getsas = (struct sockaddr_storage *)(void *)ugetsas.reply.data;
356: struct ngm_mkpeer mkpeer;
357: struct sockaddr_storage sas;
358: char hook[NG_HOOKSIZ];
359: char namebuf[64];
360: char buf[32], buf2[32];
361: char hostname[MAXHOSTNAMELEN];
362: ng_ID_t node_id;
363: int csock = -1;
364: int dsock = -1;
365: struct ghash_walk walk;
366: u_int32_t cap;
367: u_int16_t win;
368:
369: pi->opened=1;
370:
371: if (pi->incoming == 1) {
372: Log(LG_PHYS2, ("[%s] L2tpOpen() on incoming call", l->name));
373: if (l->state==PHYS_STATE_READY) {
374: l->state = PHYS_STATE_UP;
375: if (pi->outcall) {
376: pi->sync = 1;
377: if (l->rep) {
378: uint32_t fr;
379: avps = ppp_l2tp_avp_list_create();
380: if (RepIsSync(l)) {
381: fr = htonl(L2TP_FRAMING_SYNC);
382: } else {
383: fr = htonl(L2TP_FRAMING_ASYNC);
384: pi->sync = 0;
385: }
386: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
387: &fr, sizeof(fr)) == -1) {
388: Perror("[%s] ppp_l2tp_avp_list_append",
389: l->name);
390: }
391: } else {
392: avps = NULL;
393: }
394: Log(LG_PHYS, ("[%s] L2TP: Call #%u connected", l->name,
395: ppp_l2tp_sess_get_serial(pi->sess)));
396: ppp_l2tp_connected(pi->sess, avps);
397: if (avps)
398: ppp_l2tp_avp_list_destroy(&avps);
399: }
400: L2tpHookUp(l);
401: PhysUp(l);
402: }
403: return;
404: }
405:
406: /* Sanity check. */
407: if (l->state != PHYS_STATE_DOWN) {
408: Log(LG_PHYS, ("[%s] L2TP: allready active", l->name));
409: return;
410: };
411:
412: l->state = PHYS_STATE_CONNECTING;
413: strlcpy(pi->callingnum, pi->conf.callingnum, sizeof(pi->callingnum));
414: strlcpy(pi->callednum, pi->conf.callednum, sizeof(pi->callednum));
415:
416: if ((!Enabled(&pi->conf.options, L2TP_CONF_RESOLVE_ONCE)) &&
417: (pi->conf.fqdn_peer_addr != NULL)) {
418: struct u_range rng;
419: if (ParseRange(pi->conf.fqdn_peer_addr, &rng, ALLOW_IPV4|ALLOW_IPV6))
420: pi->conf.peer_addr = rng;
421: }
422:
423: ghash_walk_init(gL2tpTuns, &walk);
424: while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
425: if (tun->ctrl && tun->alive && tun->active_sessions < gL2TPtunlimit &&
426: (IpAddrInRange(&pi->conf.peer_addr, &tun->peer_addr)) &&
427: (u_addrempty(&pi->conf.self_addr) || u_addrempty(&tun->self_addr) ||
428: u_addrcompare(&pi->conf.self_addr, &tun->self_addr) == 0) &&
429: (pi->conf.peer_port == 0 || pi->conf.peer_port == tun->peer_port)) {
430: pi->tun = tun;
431: tun->active_sessions++;
432: if (tun->connected) { /* if tun is connected then just initiate */
433:
434: /* Create number AVPs */
435: avps = ppp_l2tp_avp_list_create();
436: if (pi->conf.callingnum[0]) {
437: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLING_NUMBER,
438: pi->conf.callingnum, strlen(pi->conf.callingnum)) == -1) {
439: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
440: }
441: }
442: if (pi->conf.callednum[0]) {
443: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLED_NUMBER,
444: pi->conf.callednum, strlen(pi->conf.callednum)) == -1) {
445: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
446: }
447: }
448: if ((sess = ppp_l2tp_initiate(tun->ctrl,
449: Enabled(&pi->conf.options, L2TP_CONF_OUTCALL)?1:0,
450: Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0,
451: Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0,
452: avps)) == NULL) {
453: Perror("[%s] ppp_l2tp_initiate", l->name);
454: ppp_l2tp_avp_list_destroy(&avps);
455: pi->sess = NULL;
456: pi->tun = NULL;
457: tun->active_sessions--;
458: l->state = PHYS_STATE_DOWN;
459: PhysDown(l, STR_ERROR, NULL);
460: return;
461: };
462: ppp_l2tp_avp_list_destroy(&avps);
463: pi->sess = sess;
464: pi->outcall = Enabled(&pi->conf.options, L2TP_CONF_OUTCALL);
465: Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p initiated",
466: l->name, (pi->outcall?"Outgoing":"Incoming"),
467: ppp_l2tp_sess_get_serial(sess), tun->ctrl));
468: ppp_l2tp_sess_set_cookie(sess, l);
469: if (!pi->outcall) {
470: pi->sync = 1;
471: if (l->rep) {
472: uint32_t fr;
473: avps = ppp_l2tp_avp_list_create();
474: if (RepIsSync(l)) {
475: fr = htonl(L2TP_FRAMING_SYNC);
476: } else {
477: fr = htonl(L2TP_FRAMING_ASYNC);
478: pi->sync = 0;
479: }
480: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
481: &fr, sizeof(fr)) == -1) {
482: Perror("[%s] ppp_l2tp_avp_list_append",
483: l->name);
484: }
485: } else {
486: avps = NULL;
487: }
488: ppp_l2tp_connected(pi->sess, avps);
489: if (avps)
490: ppp_l2tp_avp_list_destroy(&avps);
491: }
492: } /* Else wait while it will be connected */
493: return;
494: }
495: }
496:
497: /* There is no tun which we need. Create a new one. */
498: tun = Malloc(MB_PHYS, sizeof(*tun));
499: memset(tun, 0, sizeof(*tun));
500: u_addrcopy(&pi->conf.peer_addr.addr, &tun->peer_addr);
501: tun->peer_port = pi->conf.peer_port?pi->conf.peer_port:L2TP_PORT;
502: u_addrcopy(&pi->conf.self_addr, &tun->self_addr);
503: tun->self_port = pi->conf.self_port;
504: tun->alive = 1;
505: tun->connected = 0;
506:
507: /* Create vendor name AVP */
508: avps = ppp_l2tp_avp_list_create();
509:
510: if (pi->conf.hostname[0] != 0) {
511: strlcpy(hostname, pi->conf.hostname, sizeof(hostname));
512: } else {
513: (void)gethostname(hostname, sizeof(hostname) - 1);
514: hostname[sizeof(hostname) - 1] = '\0';
515: }
516: cap = htonl(L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG);
517: win = htons(8); /* XXX: this value is empirical. */
518: if ((ppp_l2tp_avp_list_append(avps, 1, 0, AVP_HOST_NAME,
519: hostname, strlen(hostname)) == -1) ||
1.1.1.3 misho 520: (ppp_l2tp_avp_list_append(avps, 0, 0, AVP_VENDOR_NAME,
1.1 misho 521: MPD_VENDOR, strlen(MPD_VENDOR)) == -1) ||
522: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_BEARER_CAPABILITIES,
523: &cap, sizeof(cap)) == -1) ||
524: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RECEIVE_WINDOW_SIZE,
525: &win, sizeof(win)) == -1)) {
526: Perror("L2TP: ppp_l2tp_avp_list_append");
527: goto fail;
528: }
529:
530: /* Create a new control connection */
531: if ((tun->ctrl = ppp_l2tp_ctrl_create(gPeventCtx, &gGiantMutex,
532: &ppp_l2tp_server_ctrl_cb, u_addrtoid(&tun->peer_addr),
533: &node_id, hook, avps,
534: pi->conf.secret, strlen(pi->conf.secret),
535: Enabled(&pi->conf.options, L2TP_CONF_HIDDEN))) == NULL) {
536: Perror("[%s] ppp_l2tp_ctrl_create", l->name);
537: goto fail;
538: }
539: ppp_l2tp_ctrl_set_cookie(tun->ctrl, tun);
540:
541: Log(LG_PHYS, ("L2TP: Initiating control connection %p %s %u <-> %s %u",
542: tun->ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
543: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
544:
545: /* Get a temporary netgraph socket node */
546: if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
547: Perror("[%s] NgMkSockNode", l->name);
548: goto fail;
549: }
550:
551: /* Attach a new UDP socket to "lower" hook */
552: snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
553: memset(&mkpeer, 0, sizeof(mkpeer));
554: strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
555: strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
556: if (tun->peer_addr.family==AF_INET6) {
557: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
558: } else {
559: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "inet/dgram/udp");
560: }
561: if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
562: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
563: Perror("[%s] mkpeer", l->name);
564: goto fail;
565: }
566:
567: /* Point name at ksocket node */
568: strlcat(namebuf, hook, sizeof(namebuf));
569:
570: /* Make UDP port reusable */
571: memset(&sockopt_buf, 0, sizeof(sockopt_buf));
572: sockopt->level = SOL_SOCKET;
573: sockopt->name = SO_REUSEADDR;
574: memcpy(sockopt->value, &one, sizeof(int));
575: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
576: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
577: Perror("[%s] setsockopt", l->name);
578: goto fail;
579: }
580: sockopt->name = SO_REUSEPORT;
581: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
582: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
583: Perror("[%s] setsockopt", l->name);
584: goto fail;
585: }
586:
1.1.1.4 ! misho 587: if (!u_addrempty(&tun->self_addr) || tun->self_port != 0) {
1.1 misho 588: /* Bind socket to a new port */
589: u_addrtosockaddr(&tun->self_addr,tun->self_port,&sas);
590: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
591: NGM_KSOCKET_BIND, &sas, sas.ss_len) == -1) {
592: Perror("[%s] bind", l->name);
593: goto fail;
594: }
595: }
596: /* Connect socket to remote peer's IP and port */
597: u_addrtosockaddr(&tun->peer_addr,tun->peer_port,&sas);
598: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
599: NGM_KSOCKET_CONNECT, &sas, sas.ss_len) == -1
600: && errno != EINPROGRESS) {
601: Perror("[%s] connect", l->name);
602: goto fail;
603: }
604:
605: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
606: NGM_KSOCKET_GETNAME, NULL, 0) == -1) {
607: Perror("[%s] getname send", l->name);
608: } else
609: if (NgRecvMsg(csock, &ugetsas.reply, sizeof(ugetsas), NULL) == -1) {
610: Perror("[%s] getname recv", l->name);
611: } else {
612: sockaddrtou_addr(getsas,&tun->self_addr,&tun->self_port);
613: }
614:
615: /* Add peer to our hash table */
616: if (ghash_put(gL2tpTuns, tun) == -1) {
617: Perror("[%s] ghash_put", l->name);
618: goto fail;
619: }
620: pi->tun = tun;
621: tun->active_sessions++;
622: Log(LG_PHYS2, ("L2TP: Control connection %p %s %u <-> %s %u initiated",
623: tun->ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
624: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
625: ppp_l2tp_ctrl_initiate(tun->ctrl);
626:
627: /* Clean up and return */
628: ppp_l2tp_avp_list_destroy(&avps);
629: (void)close(csock);
630: (void)close(dsock);
631: return;
632:
633: fail:
634: /* Clean up after failure */
635: if (csock != -1)
636: (void)close(csock);
637: if (dsock != -1)
638: (void)close(dsock);
639: if (tun != NULL) {
640: ppp_l2tp_ctrl_destroy(&tun->ctrl);
641: Freee(tun);
642: }
643: l->state = PHYS_STATE_DOWN;
644: PhysDown(l, STR_ERROR, NULL);
645: }
646:
647: /*
648: * L2tpClose()
649: */
650:
651: static void
652: L2tpClose(Link l)
653: {
654: L2tpInfo const pi = (L2tpInfo) l->info;
655:
656: pi->opened = 0;
657: pi->incoming = 0;
658: pi->outcall = 0;
659: if (l->state == PHYS_STATE_DOWN)
660: return;
661: L2tpUnhook(l);
662: if (pi->sess) {
663: Log(LG_PHYS, ("[%s] L2TP: Call #%u terminated locally", l->name,
664: ppp_l2tp_sess_get_serial(pi->sess)));
665: ppp_l2tp_terminate(pi->sess, L2TP_RESULT_ADMIN, 0, NULL);
666: pi->sess = NULL;
667: }
668: if (pi->tun)
669: pi->tun->active_sessions--;
670: pi->tun = NULL;
671: pi->callingnum[0]=0;
672: pi->callednum[0]=0;
673: l->state = PHYS_STATE_DOWN;
674: PhysDown(l, STR_MANUALLY, NULL);
675: }
676:
677: /*
678: * L2tpShutdown()
679: */
680:
681: static void
682: L2tpShutdown(Link l)
683: {
684: L2tpInfo const pi = (L2tpInfo) l->info;
685:
686: if (pi->conf.fqdn_peer_addr)
687: Freee(pi->conf.fqdn_peer_addr);
1.1.1.3 misho 688: if (pi->conf.peer_mask)
689: Freee(pi->conf.peer_mask);
1.1 misho 690: L2tpUnListen(l);
691: Freee(l->info);
692: }
693:
694: /*
695: * L2tpUnhook()
696: */
697:
698: static void
699: L2tpUnhook(Link l)
700: {
701: int csock = -1;
702: L2tpInfo const pi = (L2tpInfo) l->info;
703: const char *hook;
704: ng_ID_t node_id;
705: char path[NG_PATHSIZ];
706:
707: if (pi->sess) { /* avoid double close */
708:
709: /* Get this link's node and hook */
710: ppp_l2tp_sess_get_hook(pi->sess, &node_id, &hook);
711:
712: if (node_id != 0) {
713:
714: /* Get a temporary netgraph socket node */
715: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
716: Perror("L2TP: NgMkSockNode");
717: return;
718: }
719:
720: /* Disconnect session hook. */
721: snprintf(path, sizeof(path), "[%lx]:", (u_long)node_id);
722: NgFuncDisconnect(csock, l->name, path, hook);
723:
724: close(csock);
725: }
726: }
727: }
728:
729: /*
730: * L2tpOriginated()
731: */
732:
733: static int
734: L2tpOriginated(Link l)
735: {
736: L2tpInfo const l2tp = (L2tpInfo) l->info;
737:
738: return(l2tp->incoming ? LINK_ORIGINATE_REMOTE : LINK_ORIGINATE_LOCAL);
739: }
740:
741: /*
742: * L2tpIsSync()
743: */
744:
745: static int
746: L2tpIsSync(Link l)
747: {
748: L2tpInfo const l2tp = (L2tpInfo) l->info;
749:
750: return (l2tp->sync);
751: }
752:
753: static int
754: L2tpSetAccm(Link l, u_int32_t xmit, u_int32_t recv)
755: {
756: L2tpInfo const l2tp = (L2tpInfo) l->info;
757:
758: if (!l2tp->sess)
759: return (-1);
760:
761: return (ppp_l2tp_set_link_info(l2tp->sess, xmit, recv));
762: }
763:
764: static int
765: L2tpSetCallingNum(Link l, void *buf)
766: {
767: L2tpInfo const l2tp = (L2tpInfo) l->info;
768:
769: strlcpy(l2tp->conf.callingnum, buf, sizeof(l2tp->conf.callingnum));
770: return(0);
771: }
772:
773: static int
774: L2tpSetCalledNum(Link l, void *buf)
775: {
776: L2tpInfo const l2tp = (L2tpInfo) l->info;
777:
778: strlcpy(l2tp->conf.callednum, buf, sizeof(l2tp->conf.callednum));
779: return(0);
780: }
781:
782: static int
783: L2tpSelfName(Link l, void *buf, size_t buf_len)
784: {
785: L2tpInfo const l2tp = (L2tpInfo) l->info;
786:
787: if (l2tp->tun && l2tp->tun->ctrl)
788: return (ppp_l2tp_ctrl_get_self_name(l2tp->tun->ctrl, buf, buf_len));
789: ((char*)buf)[0]=0;
790: return (0);
791: }
792:
793: static int
794: L2tpPeerName(Link l, void *buf, size_t buf_len)
795: {
796: L2tpInfo const l2tp = (L2tpInfo) l->info;
797:
798: if (l2tp->tun && l2tp->tun->ctrl)
799: return (ppp_l2tp_ctrl_get_peer_name(l2tp->tun->ctrl, buf, buf_len));
800: ((char*)buf)[0]=0;
801: return (0);
802: }
803:
804: static int
805: L2tpSelfAddr(Link l, void *buf, size_t buf_len)
806: {
807: L2tpInfo const l2tp = (L2tpInfo) l->info;
808:
809: if (l2tp->tun && !u_addrempty(&l2tp->tun->self_addr)) {
810: if (u_addrtoa(&l2tp->tun->self_addr, buf, buf_len))
811: return (0);
812: else {
813: ((char*)buf)[0]=0;
814: return (-1);
815: }
816: }
817: ((char*)buf)[0]=0;
818: return (0);
819: }
820:
821: static int
822: L2tpPeerAddr(Link l, void *buf, size_t buf_len)
823: {
824: L2tpInfo const l2tp = (L2tpInfo) l->info;
825:
826: if (l2tp->tun) {
827: if (u_addrtoa(&l2tp->tun->peer_addr, buf, buf_len))
828: return(0);
829: else {
830: ((char*)buf)[0]=0;
831: return(-1);
832: }
833: }
834: ((char*)buf)[0]=0;
835: return(0);
836: }
837:
838: static int
839: L2tpPeerPort(Link l, void *buf, size_t buf_len)
840: {
841: L2tpInfo const l2tp = (L2tpInfo) l->info;
842:
843: if (l2tp->tun) {
844: if (snprintf(buf, buf_len, "%d", l2tp->tun->peer_port))
845: return(0);
846: else {
847: ((char*)buf)[0]=0;
848: return(-1);
849: }
850: }
851: ((char*)buf)[0]=0;
852: return(0);
853: }
854:
855: static int
856: L2tpPeerMacAddr(Link l, void *buf, size_t buf_len)
857: {
858: L2tpInfo const l2tp = (L2tpInfo) l->info;
859:
1.1.1.4 ! misho 860: if (buf_len < 18)
! 861: return 1;
1.1 misho 862: if (l2tp->tun && l2tp->tun->peer_iface[0]) {
1.1.1.2 misho 863: ether_ntoa_r((struct ether_addr *)l2tp->tun->peer_mac_addr, buf);
1.1 misho 864: return (0);
865: }
866: ((char*)buf)[0]=0;
867: return(0);
868: }
869:
870: static int
871: L2tpPeerIface(Link l, void *buf, size_t buf_len)
872: {
873: L2tpInfo const l2tp = (L2tpInfo) l->info;
874:
875: if (l2tp->tun && l2tp->tun->peer_iface[0]) {
876: strlcpy(buf, l2tp->tun->peer_iface, buf_len);
877: return (0);
878: }
879: ((char*)buf)[0]=0;
880: return(0);
881: }
882:
883: static int
884: L2tpCallingNum(Link l, void *buf, size_t buf_len)
885: {
886: L2tpInfo const l2tp = (L2tpInfo) l->info;
887:
888: strlcpy((char*)buf, l2tp->callingnum, buf_len);
889: return(0);
890: }
891:
892: static int
893: L2tpCalledNum(Link l, void *buf, size_t buf_len)
894: {
895: L2tpInfo const l2tp = (L2tpInfo) l->info;
896:
897: strlcpy((char*)buf, l2tp->callednum, buf_len);
898: return(0);
899: }
900:
901: /*
902: * L2tpStat()
903: */
904:
905: void
906: L2tpStat(Context ctx)
907: {
908: L2tpInfo const l2tp = (L2tpInfo) ctx->lnk->info;
909: char buf[32];
910:
911: Printf("L2TP configuration:\r\n");
912: Printf("\tSelf addr : %s, port %u",
913: u_addrtoa(&l2tp->conf.self_addr, buf, sizeof(buf)), l2tp->conf.self_port);
914: Printf("\r\n");
915: Printf("\tPeer FQDN : %s\r\n", l2tp->conf.fqdn_peer_addr);
916: Printf("\tPeer range : %s",
917: u_rangetoa(&l2tp->conf.peer_addr, buf, sizeof(buf)));
918: if (l2tp->conf.peer_port)
919: Printf(", port %u", l2tp->conf.peer_port);
920: Printf("\r\n");
921: Printf("\tHostname : %s\r\n", l2tp->conf.hostname);
1.1.1.3 misho 922: Printf("\tPeer mask : %s\r\n", l2tp->conf.peer_mask);
1.1 misho 923: Printf("\tSecret : %s\r\n", (l2tp->conf.callingnum[0])?"******":"");
924: Printf("\tCalling number: %s\r\n", l2tp->conf.callingnum);
925: Printf("\tCalled number: %s\r\n", l2tp->conf.callednum);
926: Printf("L2TP options:\r\n");
927: OptStat(ctx, &l2tp->conf.options, gConfList);
928: Printf("L2TP status:\r\n");
929: if (ctx->lnk->state != PHYS_STATE_DOWN) {
930: Printf("\tIncoming : %s\r\n", (l2tp->incoming?"YES":"NO"));
931: if (l2tp->tun) {
932: Printf("\tCurrent self : %s, port %u",
933: u_addrtoa(&l2tp->tun->self_addr, buf, sizeof(buf)), l2tp->tun->self_port);
934: L2tpSelfName(ctx->lnk, buf, sizeof(buf));
935: Printf(" (%s)\r\n", buf);
936: Printf("\tCurrent peer : %s, port %u",
937: u_addrtoa(&l2tp->tun->peer_addr, buf, sizeof(buf)), l2tp->tun->peer_port);
938: L2tpPeerName(ctx->lnk, buf, sizeof(buf));
939: Printf(" (%s)\r\n", buf);
940: if (l2tp->tun->peer_iface[0]) {
1.1.1.2 misho 941: ether_ntoa_r((struct ether_addr *)l2tp->tun->peer_mac_addr, buf);
942: Printf("\tCurrent peer : %s at %s\r\n", buf,
1.1 misho 943: l2tp->tun->peer_iface);
944: }
945: Printf("\tFraming : %s\r\n", (l2tp->sync?"Sync":"Async"));
946: }
947: Printf("\tCalling number: %s\r\n", l2tp->callingnum);
948: Printf("\tCalled number: %s\r\n", l2tp->callednum);
949: }
950: }
951:
952: /*
953: * This is called when a control connection gets opened.
954: */
955: static void
956: ppp_l2tp_ctrl_connected_cb(struct ppp_l2tp_ctrl *ctrl)
957: {
958: struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
959: struct ppp_l2tp_sess *sess;
960: struct ppp_l2tp_avp_list *avps = NULL;
961: struct sockaddr_dl hwa;
962: char buf[32], buf2[32];
963: int k;
964:
965: Log(LG_PHYS, ("L2TP: Control connection %p %s %u <-> %s %u connected",
966: ctrl, u_addrtoa(&tun->self_addr,buf,sizeof(buf)), tun->self_port,
967: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
968:
969: if (GetPeerEther(&tun->peer_addr, &hwa)) {
970: if_indextoname(hwa.sdl_index, tun->peer_iface);
971: memcpy(tun->peer_mac_addr, LLADDR(&hwa), sizeof(tun->peer_mac_addr));
972: };
973:
974: /* Examine all L2TP links. */
975: for (k = 0; k < gNumLinks; k++) {
976: Link l;
977: L2tpInfo pi;
978:
979: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
980: continue;
981:
982: l = gLinks[k];
983: pi = (L2tpInfo)l->info;
984:
985: if (pi->tun != tun)
986: continue;
987:
988: tun->connected = 1;
989: /* Create number AVPs */
990: avps = ppp_l2tp_avp_list_create();
991: if (pi->conf.callingnum[0]) {
992: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLING_NUMBER,
993: pi->conf.callingnum, strlen(pi->conf.callingnum)) == -1) {
994: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
995: }
996: }
997: if (pi->conf.callednum[0]) {
998: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_CALLED_NUMBER,
999: pi->conf.callednum, strlen(pi->conf.callednum)) == -1) {
1000: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
1001: }
1002: }
1003: if ((sess = ppp_l2tp_initiate(tun->ctrl,
1004: Enabled(&pi->conf.options, L2TP_CONF_OUTCALL)?1:0,
1005: Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0,
1006: Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0,
1007: avps)) == NULL) {
1008: Perror("ppp_l2tp_initiate");
1009: pi->sess = NULL;
1010: pi->tun = NULL;
1011: tun->active_sessions--;
1012: l->state = PHYS_STATE_DOWN;
1013: PhysDown(l, STR_ERROR, NULL);
1014: continue;
1015: };
1016: ppp_l2tp_avp_list_destroy(&avps);
1017: pi->sess = sess;
1018: pi->outcall = Enabled(&pi->conf.options, L2TP_CONF_OUTCALL);
1019: Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p initiated",
1020: l->name, (pi->outcall?"Outgoing":"Incoming"),
1021: ppp_l2tp_sess_get_serial(sess), tun->ctrl));
1022: ppp_l2tp_sess_set_cookie(sess, l);
1023: if (!pi->outcall) {
1024: pi->sync = 1;
1025: if (l->rep) {
1026: uint32_t fr;
1027: avps = ppp_l2tp_avp_list_create();
1028: if (RepIsSync(l)) {
1029: fr = htonl(L2TP_FRAMING_SYNC);
1030: } else {
1031: fr = htonl(L2TP_FRAMING_ASYNC);
1032: pi->sync = 0;
1033: }
1034: if (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_FRAMING_TYPE,
1035: &fr, sizeof(fr)) == -1) {
1036: Perror("[%s] ppp_l2tp_avp_list_append", l->name);
1037: }
1038: } else {
1039: avps = NULL;
1040: }
1041: ppp_l2tp_connected(pi->sess, avps);
1042: if (avps)
1043: ppp_l2tp_avp_list_destroy(&avps);
1044: }
1045: };
1046: }
1047:
1048: /*
1049: * This is called when a control connection is terminated for any reason
1050: * other than a call ppp_l2tp_ctrl_destroy().
1051: */
1052: static void
1053: ppp_l2tp_ctrl_terminated_cb(struct ppp_l2tp_ctrl *ctrl,
1054: u_int16_t result, u_int16_t error, const char *errmsg)
1055: {
1056: struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
1057: int k;
1058:
1.1.1.4 ! misho 1059: (void)result;
1.1 misho 1060: Log(LG_PHYS, ("L2TP: Control connection %p terminated: %d (%s)",
1061: ctrl, error, errmsg));
1062:
1063: /* Examine all L2TP links. */
1064: for (k = 0; k < gNumLinks; k++) {
1065: Link l;
1066: L2tpInfo pi;
1067:
1068: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
1069: continue;
1070:
1071: l = gLinks[k];
1072: pi = (L2tpInfo)l->info;
1073:
1074: if (pi->tun != tun)
1075: continue;
1076:
1077: l->state = PHYS_STATE_DOWN;
1078: L2tpUnhook(l);
1079: pi->sess = NULL;
1080: pi->tun = NULL;
1081: tun->active_sessions--;
1082: pi->callingnum[0]=0;
1083: pi->callednum[0]=0;
1084: PhysDown(l, STR_DROPPED, NULL);
1085: };
1086:
1087: tun->alive = 0;
1088: }
1089:
1090: /*
1091: * This is called before control connection is destroyed for any reason
1092: * other than a call ppp_l2tp_ctrl_destroy().
1093: */
1094: static void
1095: ppp_l2tp_ctrl_destroyed_cb(struct ppp_l2tp_ctrl *ctrl)
1096: {
1097: struct l2tp_tun *tun = ppp_l2tp_ctrl_get_cookie(ctrl);
1098:
1099: Log(LG_PHYS, ("L2TP: Control connection %p destroyed", ctrl));
1100:
1101: ghash_remove(gL2tpTuns, tun);
1102: Freee(tun);
1103: }
1104:
1105: /*
1106: * This callback is used to report the peer's initiating a new incoming
1107: * or outgoing call.
1108: */
1109: static void
1110: ppp_l2tp_initiated_cb(struct ppp_l2tp_ctrl *ctrl,
1111: struct ppp_l2tp_sess *sess, int out,
1112: const struct ppp_l2tp_avp_list *avps,
1113: u_char *include_length, u_char *enable_dseq)
1114: {
1115: struct l2tp_tun *const tun = ppp_l2tp_ctrl_get_cookie(ctrl);
1.1.1.3 misho 1116: char *peername = ppp_l2tp_ctrl_get_peer_name_p(ctrl);
1.1 misho 1117: struct ppp_l2tp_avp_ptrs *ptrs = NULL;
1118: Link l = NULL;
1119: L2tpInfo pi = NULL;
1120: int k;
1121:
1122: /* Convert AVP's to friendly form */
1123: if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
1124: Perror("L2TP: error decoding AVP list");
1125: ppp_l2tp_terminate(sess, L2TP_RESULT_ERROR,
1126: L2TP_ERROR_GENERIC, strerror(errno));
1127: return;
1128: }
1129:
1130: Log(LG_PHYS, ("L2TP: %s call #%u via connection %p received",
1131: (out?"Outgoing":"Incoming"),
1132: ppp_l2tp_sess_get_serial(sess), ctrl));
1133:
1134: if (gShutdownInProgress) {
1135: Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
1136: goto failed;
1137: }
1138:
1139: if (OVERLOAD()) {
1140: Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
1141: goto failed;
1142: }
1143:
1144: /* Examine all L2TP links. */
1145: for (k = 0; k < gNumLinks; k++) {
1146: Link l2;
1147: L2tpInfo pi2;
1148:
1149: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
1150: continue;
1151:
1152: l2 = gLinks[k];
1153: pi2 = (L2tpInfo)l2->info;
1154:
1155: if ((!PhysIsBusy(l2)) &&
1156: Enabled(&l2->conf.options, LINK_CONF_INCOMING) &&
1157: ((u_addrempty(&pi2->conf.self_addr)) || (u_addrcompare(&pi2->conf.self_addr, &tun->self_addr) == 0)) &&
1158: (pi2->conf.self_port == 0 || pi2->conf.self_port == tun->self_port) &&
1159: (IpAddrInRange(&pi2->conf.peer_addr, &tun->peer_addr)) &&
1.1.1.3 misho 1160: (pi2->conf.peer_port == 0 || pi2->conf.peer_port == tun->peer_port) &&
1161: (peername == NULL || *peername == 0 || pi2->conf.peer_mask == 0 || fnmatch(pi2->conf.peer_mask, peername, 0) == 0)) {
1.1 misho 1162:
1163: if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
1164: l = l2;
1165: pi = pi2;
1166: if (u_rangehost(&pi->conf.peer_addr)) {
1167: break; /* Nothing could be better */
1168: }
1169: }
1170: }
1171: }
1172: if (l != NULL && l->tmpl)
1173: l = LinkInst(l, NULL, 0, 0);
1174:
1175: if (l != NULL) {
1176: pi = (L2tpInfo)l->info;
1177: Log(LG_PHYS, ("[%s] L2TP: %s call #%u via control connection %p accepted",
1178: l->name, (out?"Outgoing":"Incoming"),
1179: ppp_l2tp_sess_get_serial(sess), ctrl));
1.1.1.3 misho 1180: if (peername && *peername)
1181: Log(LG_PHYS2, ("[%s] L2TP: Call #%u remote hostname is %s",
1182: l->name, ppp_l2tp_sess_get_serial(sess), peername));
1.1 misho 1183:
1184: if (out)
1185: l->state = PHYS_STATE_READY;
1186: else
1187: l->state = PHYS_STATE_CONNECTING;
1188: pi->incoming = 1;
1189: pi->outcall = out;
1190: pi->tun = tun;
1191: tun->active_sessions++;
1192: pi->sess = sess;
1.1.1.4 ! misho 1193: if (ptrs->callingnum)
1.1 misho 1194: strlcpy(pi->callingnum, ptrs->callingnum->number, sizeof(pi->callingnum));
1.1.1.4 ! misho 1195: if (ptrs->callednum)
1.1 misho 1196: strlcpy(pi->callednum, ptrs->callednum->number, sizeof(pi->callednum));
1197:
1198: *include_length = (Enabled(&pi->conf.options, L2TP_CONF_LENGTH)?1:0);
1199: *enable_dseq = (Enabled(&pi->conf.options, L2TP_CONF_DATASEQ)?1:0);
1200:
1201: PhysIncoming(l);
1202:
1203: ppp_l2tp_sess_set_cookie(sess, l);
1204: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1205: return;
1206: }
1207: Log(LG_PHYS, ("L2TP: No free link with requested parameters "
1208: "was found"));
1209: failed:
1210: ppp_l2tp_terminate(sess, L2TP_RESULT_AVAIL_TEMP, 0, NULL);
1211: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1212: }
1213:
1214: /*
1215: * This callback is used to report successful connection of a remotely
1216: * initiated incoming call (see ppp_l2tp_initiated_t) or a locally initiated
1217: * outgoing call (see ppp_l2tp_initiate()).
1218: */
1219: static void
1220: ppp_l2tp_connected_cb(struct ppp_l2tp_sess *sess,
1221: const struct ppp_l2tp_avp_list *avps)
1222: {
1223: Link l;
1224: L2tpInfo pi;
1225: struct ppp_l2tp_avp_ptrs *ptrs = NULL;
1226:
1227: l = ppp_l2tp_sess_get_cookie(sess);
1228: pi = (L2tpInfo)l->info;
1229:
1230: Log(LG_PHYS, ("[%s] L2TP: Call #%u connected", l->name,
1231: ppp_l2tp_sess_get_serial(sess)));
1232:
1233: if ((pi->incoming != pi->outcall) && avps != NULL) {
1234: /* Convert AVP's to friendly form */
1235: if ((ptrs = ppp_l2tp_avp_list2ptrs(avps)) == NULL) {
1236: Perror("L2TP: error decoding AVP list");
1237: } else {
1238: if (ptrs->framing && ptrs->framing->sync) {
1239: pi->sync = 1;
1240: } else {
1241: pi->sync = 0;
1242: }
1243: ppp_l2tp_avp_ptrs_destroy(&ptrs);
1244: }
1245: }
1246:
1247: if (pi->opened) {
1248: l->state = PHYS_STATE_UP;
1249: L2tpHookUp(l);
1250: PhysUp(l);
1251: } else {
1252: l->state = PHYS_STATE_READY;
1253: }
1254: }
1255:
1256: /*
1257: * This callback is called when any call, whether successfully connected
1258: * or not, is terminated for any reason other than explict termination
1259: * from the link side (via a call to either ppp_l2tp_terminate() or
1260: * ppp_l2tp_ctrl_destroy()).
1261: */
1262: static void
1263: ppp_l2tp_terminated_cb(struct ppp_l2tp_sess *sess,
1264: u_int16_t result, u_int16_t error, const char *errmsg)
1265: {
1266: char buf[128];
1267: Link l;
1268: L2tpInfo pi;
1269:
1270: l = ppp_l2tp_sess_get_cookie(sess);
1271: pi = (L2tpInfo) l->info;
1272:
1273: /* Control side is notifying us session is down */
1274: snprintf(buf, sizeof(buf), "result=%u error=%u errmsg=\"%s\"",
1275: result, error, (errmsg != NULL) ? errmsg : "");
1276: Log(LG_PHYS, ("[%s] L2TP: call #%u terminated: %s", l->name,
1277: ppp_l2tp_sess_get_serial(sess), buf));
1278:
1279: l->state = PHYS_STATE_DOWN;
1280: L2tpUnhook(l);
1281: pi->sess = NULL;
1282: if (pi->tun)
1283: pi->tun->active_sessions--;
1284: pi->tun = NULL;
1285: pi->callingnum[0]=0;
1286: pi->callednum[0]=0;
1287: PhysDown(l, STR_DROPPED, NULL);
1288: }
1289:
1290: /*
1291: * This callback called on receiving link info from peer.
1292: */
1293: void
1294: ppp_l2tp_set_link_info_cb(struct ppp_l2tp_sess *sess,
1295: u_int32_t xmit, u_int32_t recv)
1296: {
1297: Link l = ppp_l2tp_sess_get_cookie(sess);
1298:
1299: if (l->rep != NULL) {
1300: RepSetAccm(l, xmit, recv);
1301: }
1302: }
1303:
1304: /*
1305: * Connect L2TP and link hooks.
1306: */
1307:
1308: static void
1309: L2tpHookUp(Link l)
1310: {
1311: int csock = -1;
1312: L2tpInfo pi = (L2tpInfo)l->info;
1313: const char *hook;
1314: ng_ID_t node_id;
1315: char path[NG_PATHSIZ];
1316: struct ngm_connect cn;
1317:
1318: /* Get a temporary netgraph socket node */
1319: if (NgMkSockNode(NULL, &csock, NULL) == -1) {
1320: Perror("L2TP: NgMkSockNode");
1321: goto fail;
1322: }
1323:
1324: /* Get this link's node and hook */
1325: ppp_l2tp_sess_get_hook(pi->sess, &node_id, &hook);
1326:
1327: /* Initialize cn */
1328: memset(&cn, 0, sizeof(cn));
1329:
1330: /* Connect our ng_ppp(4) node link hook and ng_l2tp(4) node. */
1331: if (!PhysGetUpperHook(l, cn.path, cn.peerhook)) {
1332: Log(LG_PHYS, ("[%s] L2TP: can't get upper hook", l->name));
1333: goto fail;
1334: }
1335: snprintf(path, sizeof(path), "[%lx]:", (u_long)node_id);
1336: strlcpy(cn.ourhook, hook, sizeof(cn.ourhook));
1337: if (NgSendMsg(csock, path, NGM_GENERIC_COOKIE, NGM_CONNECT,
1338: &cn, sizeof(cn)) < 0) {
1339: Perror("[%s] L2TP: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
1340: l->name, path, cn.ourhook, cn.path, cn.peerhook);
1341: goto fail;
1342: }
1343: ppp_l2tp_sess_hooked(pi->sess);
1344: close(csock);
1345: return;
1346:
1347: fail:
1348: /* Clean up after failure */
1349: ppp_l2tp_terminate(pi->sess, L2TP_RESULT_ERROR,
1350: L2TP_ERROR_GENERIC, strerror(errno));
1351: pi->sess = NULL;
1352: if (csock != -1)
1353: (void)close(csock);
1354: }
1355:
1356: /*
1357: * Read an incoming packet that might be a new L2TP connection.
1358: */
1359:
1360: static void
1361: L2tpServerEvent(int type, void *arg)
1362: {
1363: struct l2tp_server *const s = arg;
1364: L2tpInfo pi = NULL;
1365: struct ppp_l2tp_avp_list *avps = NULL;
1366: struct l2tp_tun *tun = NULL;
1367: union {
1368: u_char buf[sizeof(struct ng_ksocket_sockopt) + sizeof(int)];
1369: struct ng_ksocket_sockopt sockopt;
1370: } sockopt_buf;
1371: struct ng_ksocket_sockopt *const sockopt = &sockopt_buf.sockopt;
1372: struct ngm_connect connect;
1373: struct ngm_rmhook rmhook;
1374: struct ngm_mkpeer mkpeer;
1375: struct sockaddr_storage peer_sas;
1376: struct sockaddr_storage sas;
1377: const size_t bufsize = 8192;
1378: u_int16_t *buf = NULL;
1379: char hook[NG_HOOKSIZ];
1380: char hostname[MAXHOSTNAMELEN];
1381: socklen_t sas_len;
1382: char namebuf[64];
1383: char buf1[32], buf2[32];
1384: ng_ID_t node_id;
1385: int csock = -1;
1386: int dsock = -1;
1387: int len;
1388: u_int32_t cap;
1389: u_int16_t win;
1390: int k;
1391:
1.1.1.4 ! misho 1392: (void)type;
1.1 misho 1393: /* Allocate buffer */
1394: buf = Malloc(MB_PHYS, bufsize);
1395:
1396: /* Read packet */
1397: sas_len = sizeof(peer_sas);
1398: if ((len = recvfrom(s->sock, buf, bufsize, 0,
1399: (struct sockaddr *)&peer_sas, &sas_len)) == -1) {
1400: Perror("L2TP: recvfrom");
1401: goto fail;
1402: }
1403:
1404: /* Drop it if it's not an initial L2TP packet */
1405: if (len < 12)
1406: goto fail;
1407: if ((ntohs(buf[0]) & 0xcb0f) != 0xc802 || ntohs(buf[1]) < 12
1408: || buf[2] != 0 || buf[3] != 0 || buf[4] != 0 || buf[5] != 0)
1409: goto fail;
1410:
1411: /* Create a new tun */
1412: tun = Malloc(MB_PHYS, sizeof(*tun));
1413: sockaddrtou_addr(&peer_sas,&tun->peer_addr,&tun->peer_port);
1414: u_addrcopy(&s->self_addr, &tun->self_addr);
1415: tun->self_port = s->self_port;
1416: tun->alive = 1;
1417:
1418: Log(LG_PHYS, ("Incoming L2TP packet from %s %d",
1419: u_addrtoa(&tun->peer_addr, namebuf, sizeof(namebuf)), tun->peer_port));
1420:
1421: /* Examine all L2TP links to get best possible fit tunnel parameters. */
1422: for (k = 0; k < gNumLinks; k++) {
1423: Link l2;
1424: L2tpInfo pi2;
1425:
1426: if (!gLinks[k] || gLinks[k]->type != &gL2tpPhysType)
1427: continue;
1428:
1429: l2 = gLinks[k];
1430: pi2 = (L2tpInfo)l2->info;
1431:
1432: /* Simplified comparation as it is not a final one. */
1433: if ((!PhysIsBusy(l2)) &&
1434: (pi2->server == s) &&
1435: (IpAddrInRange(&pi2->conf.peer_addr, &tun->peer_addr)) &&
1436: (pi2->conf.peer_port == 0 || pi2->conf.peer_port == tun->peer_port)) {
1437:
1438: if (pi == NULL || pi2->conf.peer_addr.width > pi->conf.peer_addr.width) {
1439: pi = pi2;
1440: if (u_rangehost(&pi->conf.peer_addr)) {
1441: break; /* Nothing could be better */
1442: }
1443: }
1444: }
1445: }
1446: if (pi == NULL) {
1447: Log(LG_PHYS, ("L2TP: No link with requested parameters "
1448: "was found"));
1449: goto fail;
1450: }
1451:
1452: /* Create vendor name AVP */
1453: avps = ppp_l2tp_avp_list_create();
1454:
1455: if (pi->conf.hostname[0] != 0) {
1456: strlcpy(hostname, pi->conf.hostname, sizeof(hostname));
1457: } else {
1458: (void)gethostname(hostname, sizeof(hostname) - 1);
1459: hostname[sizeof(hostname) - 1] = '\0';
1460: }
1461: cap = htonl(L2TP_BEARER_DIGITAL|L2TP_BEARER_ANALOG);
1462: win = htons(8); /* XXX: this value is empirical. */
1463: if ((ppp_l2tp_avp_list_append(avps, 1, 0, AVP_HOST_NAME,
1464: hostname, strlen(hostname)) == -1) ||
1465: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_VENDOR_NAME,
1466: MPD_VENDOR, strlen(MPD_VENDOR)) == -1) ||
1467: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_BEARER_CAPABILITIES,
1468: &cap, sizeof(cap)) == -1) ||
1469: (ppp_l2tp_avp_list_append(avps, 1, 0, AVP_RECEIVE_WINDOW_SIZE,
1470: &win, sizeof(win)) == -1)) {
1471: Perror("L2TP: ppp_l2tp_avp_list_append");
1472: goto fail;
1473: }
1474:
1475: /* Create a new control connection */
1476: if ((tun->ctrl = ppp_l2tp_ctrl_create(gPeventCtx, &gGiantMutex,
1477: &ppp_l2tp_server_ctrl_cb, u_addrtoid(&tun->peer_addr),
1478: &node_id, hook, avps,
1479: pi->conf.secret, strlen(pi->conf.secret),
1480: Enabled(&pi->conf.options, L2TP_CONF_HIDDEN))) == NULL) {
1481: Perror("L2TP: ppp_l2tp_ctrl_create");
1482: goto fail;
1483: }
1484: ppp_l2tp_ctrl_set_cookie(tun->ctrl, tun);
1485:
1486: /* Get a temporary netgraph socket node */
1487: if (NgMkSockNode(NULL, &csock, &dsock) == -1) {
1488: Perror("L2TP: NgMkSockNode");
1489: goto fail;
1490: }
1491:
1492: /* Connect to l2tp netgraph node "lower" hook */
1493: snprintf(namebuf, sizeof(namebuf), "[%lx]:", (u_long)node_id);
1494: memset(&connect, 0, sizeof(connect));
1495: strlcpy(connect.path, namebuf, sizeof(connect.path));
1496: strlcpy(connect.ourhook, hook, sizeof(connect.ourhook));
1497: strlcpy(connect.peerhook, hook, sizeof(connect.peerhook));
1498: if (NgSendMsg(csock, ".:", NGM_GENERIC_COOKIE,
1499: NGM_CONNECT, &connect, sizeof(connect)) == -1) {
1500: Perror("L2TP: connect");
1501: goto fail;
1502: }
1503:
1504: /* Write the received packet to the node */
1505: if (NgSendData(dsock, hook, (u_char *)buf, len) == -1) {
1506: Perror("L2TP: NgSendData");
1507: goto fail;
1508: }
1509:
1510: /* Disconnect from netgraph node "lower" hook */
1511: memset(&rmhook, 0, sizeof(rmhook));
1512: strlcpy(rmhook.ourhook, hook, sizeof(rmhook.ourhook));
1513: if (NgSendMsg(csock, ".:", NGM_GENERIC_COOKIE,
1514: NGM_RMHOOK, &rmhook, sizeof(rmhook)) == -1) {
1515: Perror("L2TP: rmhook");
1516: goto fail;
1517: }
1518:
1519: /* Attach a new UDP socket to "lower" hook */
1520: memset(&mkpeer, 0, sizeof(mkpeer));
1521: strlcpy(mkpeer.type, NG_KSOCKET_NODE_TYPE, sizeof(mkpeer.type));
1522: strlcpy(mkpeer.ourhook, hook, sizeof(mkpeer.ourhook));
1523: if (s->self_addr.family==AF_INET6) {
1524: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "%d/%d/%d", PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
1525: } else {
1526: snprintf(mkpeer.peerhook, sizeof(mkpeer.peerhook), "inet/dgram/udp");
1527: }
1528: if (NgSendMsg(csock, namebuf, NGM_GENERIC_COOKIE,
1529: NGM_MKPEER, &mkpeer, sizeof(mkpeer)) == -1) {
1530: Perror("L2TP: mkpeer");
1531: goto fail;
1532: }
1533:
1534: /* Point name at ksocket node */
1535: strlcat(namebuf, hook, sizeof(namebuf));
1536:
1537: /* Make UDP port reusable */
1538: memset(&sockopt_buf, 0, sizeof(sockopt_buf));
1539: sockopt->level = SOL_SOCKET;
1540: sockopt->name = SO_REUSEADDR;
1541: memcpy(sockopt->value, &one, sizeof(int));
1542: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1543: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
1544: Perror("L2TP: setsockopt");
1545: goto fail;
1546: }
1547: sockopt->name = SO_REUSEPORT;
1548: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1549: NGM_KSOCKET_SETOPT, sockopt, sizeof(sockopt_buf)) == -1) {
1550: Perror("L2TP: setsockopt");
1551: goto fail;
1552: }
1553:
1554: /* Bind socket to a new port */
1555: u_addrtosockaddr(&s->self_addr,s->self_port,&sas);
1556: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1557: NGM_KSOCKET_BIND, &sas, sas.ss_len) == -1) {
1558: Perror("L2TP: bind");
1559: goto fail;
1560: }
1561:
1562: /* Connect socket to remote peer's IP and port */
1563: if (NgSendMsg(csock, namebuf, NGM_KSOCKET_COOKIE,
1564: NGM_KSOCKET_CONNECT, &peer_sas, peer_sas.ss_len) == -1
1565: && errno != EINPROGRESS) {
1566: Perror("L2TP: connect");
1567: goto fail;
1568: }
1569:
1570: /* Add peer to our hash table */
1571: if (ghash_put(gL2tpTuns, tun) == -1) {
1572: Perror("L2TP: ghash_put");
1573: goto fail;
1574: }
1575:
1576: Log(LG_PHYS2, ("L2TP: Control connection %p %s %u <-> %s %u accepted",
1577: tun->ctrl, u_addrtoa(&tun->self_addr,buf1,sizeof(buf1)), tun->self_port,
1578: u_addrtoa(&tun->peer_addr,buf2,sizeof(buf2)), tun->peer_port));
1579:
1580: /* Clean up and return */
1581: ppp_l2tp_avp_list_destroy(&avps);
1582: (void)close(csock);
1583: (void)close(dsock);
1584: Freee(buf);
1585: return;
1586:
1587: fail:
1588: /* Clean up after failure */
1589: if (csock != -1)
1590: (void)close(csock);
1591: if (dsock != -1)
1592: (void)close(dsock);
1593: if (tun != NULL) {
1594: ppp_l2tp_ctrl_destroy(&tun->ctrl);
1595: Freee(tun);
1596: }
1597: ppp_l2tp_avp_list_destroy(&avps);
1598: Freee(buf);
1599: }
1600:
1601:
1602: /*
1603: * L2tpListen()
1604: */
1605:
1606: static int
1607: L2tpListen(Link l)
1608: {
1609: L2tpInfo p = (L2tpInfo)l->info;
1610: struct l2tp_server *s;
1611: struct sockaddr_storage sa;
1612: char buf[48];
1613: struct ghash_walk walk;
1614:
1615: if (p->server)
1616: return(1);
1617:
1618: ghash_walk_init(gL2tpServers, &walk);
1619: while ((s = ghash_walk_next(gL2tpServers, &walk)) != NULL) {
1620: if ((u_addrcompare(&s->self_addr, &p->conf.self_addr) == 0) &&
1621: s->self_port == (p->conf.self_port?p->conf.self_port:L2TP_PORT)) {
1622: s->refs++;
1623: p->server = s;
1624: return(1);
1625: }
1626: }
1627:
1628: s = Malloc(MB_PHYS, sizeof(struct l2tp_server));
1629: s->refs = 1;
1630: u_addrcopy(&p->conf.self_addr, &s->self_addr);
1631: s->self_port = p->conf.self_port?p->conf.self_port:L2TP_PORT;
1632:
1633: /* Setup UDP socket that listens for new connections */
1634: if (s->self_addr.family==AF_INET6) {
1635: s->sock = socket(PF_INET6, SOCK_DGRAM, IPPROTO_UDP);
1636: } else {
1637: s->sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
1638: }
1639: if (s->sock == -1) {
1640: Perror("L2TP: socket");
1641: goto fail;
1642: }
1643: if (setsockopt(s->sock, SOL_SOCKET,
1644: SO_REUSEADDR, &one, sizeof(one)) == -1) {
1645: Perror("L2TP: setsockopt");
1646: goto fail;
1647: }
1648: if (setsockopt(s->sock, SOL_SOCKET,
1649: SO_REUSEPORT, &one, sizeof(one)) == -1) {
1650: Perror("L2TP: setsockopt");
1651: goto fail;
1652: }
1653: u_addrtosockaddr(&s->self_addr, s->self_port, &sa);
1654: if (bind(s->sock, (struct sockaddr *)&sa, sa.ss_len) == -1) {
1655: Perror("L2TP: bind");
1656: goto fail;
1657: }
1658:
1659: EventRegister(&s->event, EVENT_READ, s->sock,
1660: EVENT_RECURRING, L2tpServerEvent, s);
1661:
1662: Log(LG_PHYS, ("L2TP: waiting for connection on %s %u",
1663: u_addrtoa(&s->self_addr, buf, sizeof(buf)), s->self_port));
1664:
1665: p->server = s;
1666: ghash_put(gL2tpServers, s);
1667: return (1);
1668: fail:
1669: if (s->sock)
1670: close(s->sock);
1671: Freee(s);
1672: return (0);
1673: }
1674:
1675: /*
1676: * L2tpUnListen()
1677: */
1678:
1679: static void
1680: L2tpUnListen(Link l)
1681: {
1682: L2tpInfo p = (L2tpInfo)l->info;
1683: struct l2tp_server *s = p->server;
1684: char buf[48];
1685:
1686: if (!s)
1687: return;
1688:
1689: s->refs--;
1690: if (s->refs == 0) {
1691: Log(LG_PHYS, ("L2TP: stop waiting for connection on %s %u",
1692: u_addrtoa(&s->self_addr, buf, sizeof(buf)), s->self_port));
1693:
1694: ghash_remove(gL2tpServers, s);
1695: EventUnRegister(&s->event);
1696: if (s->sock)
1697: close(s->sock);
1698: Freee(s);
1699: p->server = NULL;
1700: }
1701: return;
1702: }
1703:
1704: /*
1705: * L2tpNodeUpdate()
1706: */
1707:
1708: static void
1709: L2tpNodeUpdate(Link l)
1710: {
1711: L2tpInfo const pi = (L2tpInfo) l->info;
1712: if (!pi->server) {
1713: if (Enabled(&l->conf.options, LINK_CONF_INCOMING))
1714: L2tpListen(l);
1715: } else {
1716: if (!Enabled(&l->conf.options, LINK_CONF_INCOMING))
1717: L2tpUnListen(l);
1718: }
1719: }
1720:
1721: /*
1722: * L2tpSetCommand()
1723: */
1724:
1725: static int
1.1.1.4 ! misho 1726: L2tpSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1727: {
1728: L2tpInfo const l2tp = (L2tpInfo) ctx->lnk->info;
1729: char **fqdn_peer_addr = &l2tp->conf.fqdn_peer_addr;
1.1.1.3 misho 1730: char **peer_mask = &l2tp->conf.peer_mask;
1.1 misho 1731: struct u_range rng;
1732: int port;
1733:
1734: switch ((intptr_t)arg) {
1735: case SET_SELFADDR:
1736: case SET_PEERADDR:
1737: if ((ac == 1 || ac == 2) && (intptr_t)arg == SET_PEERADDR) {
1738: if (*fqdn_peer_addr)
1739: Freee(*fqdn_peer_addr);
1740: *fqdn_peer_addr = Mstrdup(MB_PHYS, av[0]);
1741: }
1742: if (ac < 1 || ac > 2 || !ParseRange(av[0], &rng, ALLOW_IPV4|ALLOW_IPV6))
1743: return(-1);
1744: if (ac > 1) {
1745: if ((port = atoi(av[1])) < 0 || port > 0xffff)
1746: return(-1);
1747: } else {
1748: port = 0;
1749: }
1750: if ((intptr_t)arg == SET_SELFADDR) {
1751: l2tp->conf.self_addr = rng.addr;
1752: l2tp->conf.self_port = port;
1753: if (l2tp->server) {
1754: L2tpUnListen(ctx->lnk);
1755: L2tpListen(ctx->lnk);
1756: }
1757: } else {
1758: l2tp->conf.peer_addr = rng;
1759: l2tp->conf.peer_port = port;
1760: }
1761: break;
1762: case SET_CALLINGNUM:
1763: if (ac != 1)
1764: return(-1);
1765: strlcpy(l2tp->conf.callingnum, av[0], sizeof(l2tp->conf.callingnum));
1766: break;
1767: case SET_CALLEDNUM:
1768: if (ac != 1)
1769: return(-1);
1770: strlcpy(l2tp->conf.callednum, av[0], sizeof(l2tp->conf.callednum));
1771: break;
1772: case SET_HOSTNAME:
1773: if (ac != 1)
1774: return(-1);
1775: strlcpy(l2tp->conf.hostname, av[0], sizeof(l2tp->conf.hostname));
1.1.1.3 misho 1776: break;
1777: case SET_PEERMASK:
1778: if (ac != 1)
1779: return(-1);
1780: if (*peer_mask)
1781: Freee(*peer_mask);
1782: *peer_mask = Mstrdup(MB_PHYS, av[0]);
1.1 misho 1783: break;
1784: case SET_SECRET:
1785: if (ac != 1)
1786: return(-1);
1787: strlcpy(l2tp->conf.secret, av[0], sizeof(l2tp->conf.secret));
1788: break;
1789: case SET_ENABLE:
1790: EnableCommand(ac, av, &l2tp->conf.options, gConfList);
1791: break;
1792: case SET_DISABLE:
1793: DisableCommand(ac, av, &l2tp->conf.options, gConfList);
1794: break;
1795: default:
1796: assert(0);
1797: }
1798: return(0);
1799: }
1800:
1801: /*
1802: * L2tpsStat()
1803: */
1804:
1805: int
1.1.1.4 ! misho 1806: L2tpsStat(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1807: {
1808: struct l2tp_tun *tun;
1809: struct ghash_walk walk;
1810: char buf1[64], buf2[64], buf3[64];
1811:
1.1.1.4 ! misho 1812: (void)ac;
! 1813: (void)av;
! 1814: (void)arg;
! 1815:
1.1 misho 1816: Printf("Active L2TP tunnels:\r\n");
1817: ghash_walk_init(gL2tpTuns, &walk);
1818: while ((tun = ghash_walk_next(gL2tpTuns, &walk)) != NULL) {
1819:
1820: u_addrtoa(&tun->self_addr, buf1, sizeof(buf1));
1821: u_addrtoa(&tun->peer_addr, buf2, sizeof(buf2));
1822: ppp_l2tp_ctrl_stats(tun->ctrl, buf3, sizeof(buf3));
1823: Printf("%p\t %s %d <=> %s %d\t%s %d calls\r\n",
1824: tun->ctrl, buf1, tun->self_port, buf2, tun->peer_port,
1825: buf3, tun->active_sessions);
1826: }
1827:
1828: return 0;
1829: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>