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