Annotation of embedaddon/mpd/src/pppoe.c, revision 1.1.1.5.2.1
1.1 misho 1:
2: /*
3: * pppoe.c
4: *
5: * Written by Archie Cobbs <archie@freebsd.org>
6: * Copyright (c) 1995-1999 Whistle Communications, Inc. All rights reserved.
7: * See ``COPYRIGHT.whistle''
8: */
9:
10: #include "ppp.h"
11: #include "pppoe.h"
12: #include "ngfunc.h"
13: #include "log.h"
14: #include "util.h"
15:
1.1.1.2 misho 16: #include <paths.h>
1.1 misho 17: #include <net/ethernet.h>
1.1.1.5 misho 18: #include <net/if.h>
1.1 misho 19: #include <netgraph/ng_message.h>
20: #include <netgraph/ng_pppoe.h>
21: #include <netgraph/ng_ether.h>
22: #include <netgraph/ng_tee.h>
23: #include <netgraph.h>
24:
25: #include <sys/param.h>
26: #include <sys/linker.h>
27:
28: /*
29: * DEFINITIONS
30: */
31:
1.1.1.5.2.1! misho 32: #define PPPOE_MTU_MAX (ETHER_MAX_LEN_JUMBO - 8)
1.1 misho 33: #define PPPOE_MTU 1492 /* allow room for PPPoE overhead */
34: #define PPPOE_MRU 1492
35:
36: #define PPPOE_CONNECT_TIMEOUT 9
37:
38: #define ETHER_DEFAULT_HOOK NG_ETHER_HOOK_ORPHAN
39:
1.1.1.2 misho 40: #ifndef SMALL_SYSTEM
1.1.1.3 misho 41: #define PPPOE_MAXPARENTIFS 4096
1.1.1.2 misho 42: #else
43: #define PPPOE_MAXPARENTIFS 32
44: #endif
1.1 misho 45:
46: #define MAX_PATH 64 /* XXX should be NG_PATHSIZ */
47: #define MAX_SESSION 64 /* max length of PPPoE session name */
48:
1.1.1.3 misho 49: #ifndef PTT_MAX_PAYL /* PPP-Max-Payload (RFC4638) */
50: #if BYTE_ORDER == BIG_ENDIAN
51: #define PTT_MAX_PAYL (0x0120)
52: #else
53: #define PTT_MAX_PAYL (0x2001)
54: #endif
55: #endif
56:
57: /* https://tools.ietf.org/html/rfc4937 */
58: #if BYTE_ORDER == BIG_ENDIAN
59: #define MPD_PTT_CREDITS (0x0106)
60: #define MPD_PTT_METRICS (0x0107)
61: #define MPD_PTT_SEQ_NUMBER (0x0108)
62: #define MPD_PTT_HURL (0x0111)
63: #define MPD_PTT_MOTM (0x0112)
64: #define MPD_PTT_IP_ROUTE_ADD (0x0121)
65: #else
66: #define MPD_PTT_CREDITS (0x0601)
67: #define MPD_PTT_METRICS (0x0701)
68: #define MPD_PTT_SEQ_NUMBER (0x0801)
69: #define MPD_PTT_HURL (0x1101)
70: #define MPD_PTT_MOTM (0x1201)
71: #define MPD_PTT_IP_ROUTE_ADD (0x2101)
72: #endif
73:
1.1 misho 74: /* Per link private info */
75: struct pppoeinfo {
1.1.1.4 misho 76: char iface[IFNAMSIZ]; /* PPPoE interface name */
1.1 misho 77: char path[MAX_PATH]; /* PPPoE node path */
78: char hook[NG_HOOKSIZ]; /* hook on that node */
79: char session[MAX_SESSION]; /* session name */
80: char acname[PPPOE_SERVICE_NAME_SIZE]; /* AC name */
1.1.1.3 misho 81: uint16_t max_payload; /* PPP-Max-Payload (RFC4638) */
82: int mac_format; /* MAC address format */
1.1 misho 83: u_char peeraddr[6]; /* Peer MAC address */
84: char real_session[MAX_SESSION]; /* real session name */
85: char agent_cid[64]; /* Agent Circuit ID */
86: char agent_rid[64]; /* Agent Remote ID */
87: u_char incoming; /* incoming vs. outgoing */
88: u_char opened; /* PPPoE opened by phys */
1.1.1.3 misho 89: u_char mp_reply; /* PPP-Max-Payload reply from server */
1.1 misho 90: struct optinfo options;
91: struct PppoeIf *PIf; /* pointer on parent ng_pppoe info */
92: struct PppoeList *list;
93: struct pppTimer connectTimer; /* connection timeout timer */
94: };
95: typedef struct pppoeinfo *PppoeInfo;
96:
97: static u_char gNgEtherLoaded = FALSE;
98:
99: /* Set menu options */
100: enum {
101: SET_IFACE,
102: SET_SESSION,
1.1.1.3 misho 103: SET_ACNAME,
104: SET_MAX_PAYLOAD,
105: SET_MAC_FORMAT
106: };
107:
108: /* MAC format options */
109: enum {
110: MAC_UNFORMATTED = 0,
111: MAC_UNIX_LIKE,
112: MAC_CISCO_LIKE,
113: MAC_IETF
1.1 misho 114: };
115:
116: /*
117: Invariants:
118: ----------
119:
120: PPPOE_DOWN
121: - ng_pppoe(4) node does not exist
122: - pe->csock == -1
123: - Connect timeout timer is not running
124:
125: PPPOE_CONNECTING
126: - ng_pppoe(4) node exists and is connected to ether and ppp nodes
127: - pe->csock != -1
128: - Listening for control messages rec'd on pe->csock
129: - Connect timeout timer is running
130: - NGM_PPPOE_CONNECT has been sent to the ng_pppoe(4) node, and
131: no response has been received yet
132:
133: PPPOE_UP
134: - ng_pppoe(4) node exists and is connected to ether and ppp nodes
135: - pe->csock != -1
136: - Listening for control messages rec'd on pe->csock
137: - Connect timeout timer is not running
138: - NGM_PPPOE_CONNECT has been sent to the ng_pppoe(4) node, and
139: a NGM_PPPOE_SUCCESS has been received
140: */
141:
142: /*
143: * INTERNAL FUNCTIONS
144: */
145:
146: static int PppoeInit(Link l);
147: static int PppoeInst(Link l, Link lt);
148: static void PppoeOpen(Link l);
149: static void PppoeClose(Link l);
150: static void PppoeShutdown(Link l);
151: static int PppoePeerMacAddr(Link l, void *buf, size_t buf_len);
152: static int PppoePeerIface(Link l, void *buf, size_t buf_len);
153: static int PppoeCallingNum(Link l, void *buf, size_t buf_len);
154: static int PppoeCalledNum(Link l, void *buf, size_t buf_len);
155: static int PppoeSelfName(Link l, void *buf, size_t buf_len);
156: static int PppoePeerName(Link l, void *buf, size_t buf_len);
1.1.1.3 misho 157: static u_short PppoeGetMtu(Link l, int conf);
158: static u_short PppoeGetMru(Link l, int conf);
1.1 misho 159: static void PppoeCtrlReadEvent(int type, void *arg);
160: static void PppoeConnectTimeout(void *arg);
161: static void PppoeStat(Context ctx);
1.1.1.5 misho 162: static int PppoeSetCommand(Context ctx, int ac, const char *const av[], const void *arg);
1.1 misho 163: static int PppoeOriginated(Link l);
164: static int PppoeIsSync(Link l);
165: static void PppoeGetNode(Link l);
166: static void PppoeReleaseNode(Link l);
167: static int PppoeListen(Link l);
168: static int PppoeUnListen(Link l);
169: static void PppoeNodeUpdate(Link l);
170: static void PppoeListenEvent(int type, void *arg);
1.1.1.4 misho 171: static int CreatePppoeNode(struct PppoeIf *PIf, const char *iface, const char *path, const char *hook);
1.1 misho 172:
173: static void PppoeDoClose(Link l);
174:
175: /*
176: * GLOBAL VARIABLES
177: */
178:
179: const struct phystype gPppoePhysType = {
180: .name = "pppoe",
181: .descr = "PPP over Ethernet",
1.1.1.5.2.1! misho 182: .mtu = PPPOE_MTU_MAX,
1.1 misho 183: .mru = PPPOE_MRU,
184: .tmpl = 1,
185: .init = PppoeInit,
186: .inst = PppoeInst,
187: .open = PppoeOpen,
188: .close = PppoeClose,
189: .update = PppoeNodeUpdate,
190: .shutdown = PppoeShutdown,
191: .showstat = PppoeStat,
192: .originate = PppoeOriginated,
193: .issync = PppoeIsSync,
194: .peeraddr = PppoePeerMacAddr,
195: .peermacaddr = PppoePeerMacAddr,
196: .peeriface = PppoePeerIface,
197: .callingnum = PppoeCallingNum,
198: .callednum = PppoeCalledNum,
199: .selfname = PppoeSelfName,
200: .peername = PppoePeerName,
1.1.1.3 misho 201: .getmtu = PppoeGetMtu,
202: .getmru = PppoeGetMru
1.1 misho 203: };
204:
205: const struct cmdtab PppoeSetCmds[] = {
206: { "iface {name}", "Set ethernet interface to use",
207: PppoeSetCommand, NULL, 2, (void *)SET_IFACE },
208: { "service {name}", "Set PPPoE session name",
209: PppoeSetCommand, NULL, 2, (void *)SET_SESSION },
210: { "acname {name}", "Set PPPoE access concentrator name",
211: PppoeSetCommand, NULL, 2, (void *)SET_ACNAME },
1.1.1.3 misho 212: #ifdef NGM_PPPOE_SETMAXP_COOKIE
213: { "max-payload {size}", "Set PPP-Max-Payload tag",
214: PppoeSetCommand, NULL, 2, (void *)SET_MAX_PAYLOAD },
215: #endif
216: { "mac-format {format}", "Set RADIUS attribute 31 MAC format",
217: PppoeSetCommand, NULL, 2, (void *)SET_MAC_FORMAT },
1.1.1.5 misho 218: { NULL, NULL, NULL, NULL, 0, NULL }
1.1 misho 219: };
220:
221: /*
222: * INTERNAL VARIABLES
223: */
224:
225: struct PppoeList {
226: char session[MAX_SESSION];
227: int refs;
228: SLIST_ENTRY(PppoeList) next;
229: };
230:
231: struct PppoeIf {
232: char ifnodepath[MAX_PATH];
233: ng_ID_t node_id; /* pppoe node id */
234: int refs;
235: int csock; /* netgraph Control socket */
236: int dsock; /* netgraph Data socket */
237: EventRef ctrlEvent; /* listen for ctrl messages */
238: EventRef dataEvent; /* listen for data messages */
239: SLIST_HEAD(, PppoeList) list;
240: };
241:
1.1.1.5 misho 242: static struct PppoeIf PppoeIfs[PPPOE_MAXPARENTIFS];
1.1 misho 243:
1.1.1.3 misho 244: struct tagname {
245: int tag;
246: const char *name;
247: };
248:
249: static const struct tagname tag2str[] = {
250: { PTT_EOL, "End-Of-List" },
251: { PTT_SRV_NAME, "Service-Name" },
252: { PTT_AC_NAME, "AC-Name" },
253: { PTT_HOST_UNIQ, "Host-Uniq" },
254: { PTT_AC_COOKIE, "AC-Cookie" },
255: { PTT_VENDOR, "Vendor-Specific" },
256: { PTT_RELAY_SID, "Relay-Session-Id" },
257: { PTT_MAX_PAYL, "PPP-Max-Payload" },
258: { PTT_SRV_ERR, "Service-Name-Error" },
259: { PTT_SYS_ERR, "AC-System-Error" },
260: { PTT_GEN_ERR, "Generic-Error" },
261: /* RFC 4937 */
262: { MPD_PTT_CREDITS, "Credits" },
263: { MPD_PTT_METRICS, "Metrics" },
264: { MPD_PTT_SEQ_NUMBER, "Sequence Number" },
265: { MPD_PTT_HURL, "HURL" },
266: { MPD_PTT_MOTM, "MOTM" },
267: { MPD_PTT_IP_ROUTE_ADD, "IP_Route_Add" },
268: { 0, "UNKNOWN" }
269: };
270: #define NUM_TAG_NAMES (sizeof(tag2str) / sizeof(*tag2str))
271:
272:
1.1 misho 273: /*
274: * PppoeInit()
275: *
276: * Initialize device-specific data in physical layer info
277: */
278: static int
279: PppoeInit(Link l)
280: {
281: PppoeInfo pe;
282:
283: /* Allocate private struct */
284: pe = (PppoeInfo)(l->info = Malloc(MB_PHYS, sizeof(*pe)));
285: pe->incoming = 0;
286: pe->opened = 0;
1.1.1.4 misho 287: snprintf(pe->iface, sizeof(pe->iface), "undefined");
1.1 misho 288: snprintf(pe->path, sizeof(pe->path), "undefined:");
289: snprintf(pe->hook, sizeof(pe->hook), "undefined");
290: snprintf(pe->session, sizeof(pe->session), "*");
291: memset(pe->peeraddr, 0x00, ETHER_ADDR_LEN);
292: strlcpy(pe->real_session, pe->session, sizeof(pe->real_session));
293: pe->agent_cid[0] = 0;
294: pe->agent_rid[0] = 0;
295: pe->PIf = NULL;
1.1.1.3 misho 296: pe->max_payload = 0;
297: pe->mac_format = MAC_UNFORMATTED;
298: pe->mp_reply = 0;
1.1 misho 299:
300: /* Done */
301: return(0);
302: }
303:
304: /*
305: * PppoeInst()
306: *
307: * Instantiate device
308: */
309: static int
310: PppoeInst(Link l, Link lt)
311: {
312: PppoeInfo pi;
313: l->info = Mdup(MB_PHYS, lt->info, sizeof(struct pppoeinfo));
314: pi = (PppoeInfo)l->info;
315: if (pi->PIf)
316: pi->PIf->refs++;
317: if (pi->list)
318: pi->list->refs++;
319:
320: /* Done */
321: return(0);
322: }
323:
324: /*
325: * PppoeOpen()
326: */
327: static void
328: PppoeOpen(Link l)
329: {
330: PppoeInfo pe = (PppoeInfo)l->info;
331: struct ngm_connect cn;
332: union {
333: u_char buf[sizeof(struct ngpppoe_init_data) + MAX_SESSION];
334: struct ngpppoe_init_data poeid;
335: } u;
336: struct ngpppoe_init_data *const idata = &u.poeid;
337: char path[NG_PATHSIZ];
338: char session_hook[NG_HOOKSIZ];
339:
340: pe->opened=1;
341:
342: Disable(&l->conf.options, LINK_CONF_ACFCOMP); /* RFC 2516 */
343: Deny(&l->conf.options, LINK_CONF_ACFCOMP); /* RFC 2516 */
344:
345: snprintf(session_hook, sizeof(session_hook), "mpd%d-%d",
346: gPid, l->id);
347:
348: if (pe->incoming == 1) {
349: Log(LG_PHYS2, ("[%s] PppoeOpen() on incoming call", l->name));
350:
351: /* Path to the ng_tee node */
352: snprintf(path, sizeof(path), "[%x]:%s",
353: pe->PIf->node_id, session_hook);
354:
355: /* Connect ng_tee(4) node to the ng_ppp(4) node. */
356: memset(&cn, 0, sizeof(cn));
357: if (!PhysGetUpperHook(l, cn.path, cn.peerhook)) {
358: Log(LG_PHYS, ("[%s] PPPoE: can't get upper hook", l->name));
359: goto fail3;
360: }
361: snprintf(cn.ourhook, sizeof(cn.ourhook), "right");
362: if (NgSendMsg(pe->PIf->csock, path, NGM_GENERIC_COOKIE, NGM_CONNECT,
363: &cn, sizeof(cn)) < 0) {
364: Perror("[%s] PPPoE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
365: l->name, path, cn.ourhook, cn.path, cn.peerhook);
366: goto fail3;
367: }
368:
369: /* Shutdown ng_tee node */
370: if (NgFuncShutdownNode(pe->PIf->csock, l->name, path) < 0) {
371: Perror("[%s] PPPoE: Shutdown ng_tee node %s error",
372: l->name, path);
373: }
374:
375: if (l->state==PHYS_STATE_READY) {
376: TimerStop(&pe->connectTimer);
377: l->state = PHYS_STATE_UP;
378: PhysUp(l);
379: }
380: return;
381: }
382:
383: /* Sanity check. */
384: if (l->state != PHYS_STATE_DOWN) {
385: Log(LG_PHYS, ("[%s] PPPoE allready active", l->name));
386: return;
387: };
388:
389: /* Create PPPoE node if necessary. */
390: PppoeGetNode(l);
391:
392: if (!pe->PIf) {
393: Log(LG_ERR, ("[%s] PPPoE node for link is not initialized",
394: l->name));
395: goto fail;
396: }
397:
398: /* Connect our ng_ppp(4) node link hook to the ng_pppoe(4) node. */
399: strlcpy(cn.ourhook, session_hook, sizeof(cn.ourhook));
400: snprintf(path, sizeof(path), "[%x]:", pe->PIf->node_id);
401:
402: if (!PhysGetUpperHook(l, cn.path, cn.peerhook)) {
403: Log(LG_PHYS, ("[%s] PPPoE: can't get upper hook", l->name));
404: goto fail2;
405: }
406:
407: if (NgSendMsg(pe->PIf->csock, path, NGM_GENERIC_COOKIE, NGM_CONNECT,
408: &cn, sizeof(cn)) < 0) {
409: Perror("[%s] PPPoE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
410: l->name, path, cn.ourhook, cn.path, cn.peerhook);
1.1.1.5.2.1! misho 411: if (errno == ENOENT) {
! 412: PppoeReleaseNode(l);
! 413: goto fail;
! 414: }
1.1 misho 415: goto fail2;
416: }
1.1.1.3 misho 417:
418: #ifdef NGM_PPPOE_SETMAXP_COOKIE
419: if (pe->max_payload > 0)
420: Log(LG_PHYS, ("[%s] PPPoE: Set PPP-Max-Payload to '%u'",
421: l->name, pe->max_payload));
422: /* Tell the PPPoE node to set PPP-Max-Payload value (unset if 0). */
423: if (NgSendMsg(pe->PIf->csock, path, NGM_PPPOE_COOKIE, NGM_PPPOE_SETMAXP,
424: &pe->max_payload, sizeof(uint16_t)) < 0) {
425: Perror("[%s] PPPoE can't set PPP-Max-Payload value", l->name);
426: goto fail2;
427: }
428: #endif
1.1 misho 429:
430: Log(LG_PHYS, ("[%s] PPPoE: Connecting to '%s'", l->name, pe->session));
431:
432: /* Tell the PPPoE node to try to connect to a server. */
1.1.1.3 misho 433: memset(idata, 0, sizeof(struct ngpppoe_init_data));
1.1 misho 434: strlcpy(idata->hook, session_hook, sizeof(idata->hook));
435: idata->data_len = strlen(pe->session);
436: strncpy(idata->data, pe->session, MAX_SESSION);
437: if (NgSendMsg(pe->PIf->csock, path, NGM_PPPOE_COOKIE, NGM_PPPOE_CONNECT,
438: idata, sizeof(*idata) + idata->data_len) < 0) {
439: Perror("[%s] PPPoE can't request connection to server", l->name);
440: goto fail2;
441: }
442:
443: /* Set a timer to limit connection time. */
444: TimerInit(&pe->connectTimer, "PPPoE-connect",
445: PPPOE_CONNECT_TIMEOUT * SECONDS, PppoeConnectTimeout, l);
446: TimerStart(&pe->connectTimer);
447:
448: /* OK */
449: l->state = PHYS_STATE_CONNECTING;
450: strlcpy(pe->real_session, pe->session, sizeof(pe->real_session));
451: pe->agent_cid[0] = 0;
452: pe->agent_rid[0] = 0;
1.1.1.3 misho 453: pe->mp_reply = 0;
1.1 misho 454: return;
455:
456: fail3:
457: snprintf(path, sizeof(path), "[%x]:", pe->PIf->node_id);
458: fail2:
459: NgFuncDisconnect(pe->PIf->csock, l->name, path, session_hook);
460: fail:
461: PhysDown(l, STR_ERROR, NULL);
462: return;
463: }
464:
465: /*
466: * PppoeConnectTimeout()
467: */
468: static void
469: PppoeConnectTimeout(void *arg)
470: {
471: const Link l = (Link)arg;
472:
473: /* Cancel connection. */
474: Log(LG_PHYS, ("[%s] PPPoE connection timeout after %d seconds",
475: l->name, PPPOE_CONNECT_TIMEOUT));
476: PppoeDoClose(l);
477: PhysDown(l, STR_CON_FAILED0, NULL);
478: }
479:
480: /*
481: * PppoeClose()
482: */
483: static void
484: PppoeClose(Link l)
485: {
486: const PppoeInfo pe = (PppoeInfo)l->info;
487:
488: pe->opened = 0;
489: if (l->state == PHYS_STATE_DOWN)
490: return;
491: PppoeDoClose(l);
492: PhysDown(l, STR_MANUALLY, NULL);
493: }
494:
495: /*
496: * PppoeShutdown()
497: *
498: * Shut everything down and go to the PHYS_STATE_DOWN state.
499: */
500: static void
501: PppoeShutdown(Link l)
502: {
503: PppoeDoClose(l);
504: PppoeUnListen(l);
505: PppoeReleaseNode(l);
506: Freee(l->info);
507: }
508:
509: /*
510: * PppoeDoClose()
511: *
512: * Shut everything down and go to the PHYS_STATE_DOWN state.
513: */
514: static void
515: PppoeDoClose(Link l)
516: {
517: const PppoeInfo pi = (PppoeInfo)l->info;
518: char path[NG_PATHSIZ];
519: char session_hook[NG_HOOKSIZ];
520:
521: if (l->state == PHYS_STATE_DOWN)
522: return;
523:
524: snprintf(path, sizeof(path), "[%x]:", pi->PIf->node_id);
525: snprintf(session_hook, sizeof(session_hook), "mpd%d-%d",
526: gPid, l->id);
527: NgFuncDisconnect(pi->PIf->csock, l->name, path, session_hook);
528:
529: TimerStop(&pi->connectTimer);
530: l->state = PHYS_STATE_DOWN;
531: pi->incoming = 0;
532: memset(pi->peeraddr, 0x00, ETHER_ADDR_LEN);
533: pi->real_session[0] = 0;
534: pi->agent_cid[0] = 0;
535: pi->agent_rid[0] = 0;
1.1.1.3 misho 536: pi->mp_reply = 0;
1.1 misho 537: }
538:
539: /*
540: * PppoeCtrlReadEvent()
541: *
542: * Receive an incoming control message from the PPPoE node
543: */
544: static void
545: PppoeCtrlReadEvent(int type, void *arg)
546: {
547: union {
1.1.1.3 misho 548: #ifdef NGM_PPPOE_SETMAXP_COOKIE
549: u_char buf[sizeof(struct ng_mesg) + sizeof(struct ngpppoe_maxp)];
550: #else
1.1 misho 551: u_char buf[sizeof(struct ng_mesg) + sizeof(struct ngpppoe_sts)];
1.1.1.3 misho 552: #endif
1.1 misho 553: struct ng_mesg resp;
554: } u;
555: char path[NG_PATHSIZ];
556: Link l = NULL;
557: PppoeInfo pi = NULL;
558:
559: struct PppoeIf *PIf = (struct PppoeIf*)arg;
1.1.1.5 misho 560:
561: (void)type;
1.1 misho 562: /* Read control message. */
563: if (NgRecvMsg(PIf->csock, &u.resp, sizeof(u), path) < 0) {
564: Perror("PPPoE: error reading message from \"%s\"", path);
565: return;
566: }
567: if (u.resp.header.typecookie != NGM_PPPOE_COOKIE) {
568: Log(LG_ERR, ("PPPoE: rec'd cookie %lu from \"%s\"",
569: (u_long)u.resp.header.typecookie, path));
570: return;
571: }
572:
573: switch (u.resp.header.cmd) {
574: case NGM_PPPOE_SUCCESS:
575: case NGM_PPPOE_FAIL:
576: case NGM_PPPOE_CLOSE:
1.1.1.3 misho 577: #ifdef NGM_PPPOE_SETMAXP_COOKIE
578: case NGM_PPPOE_SETMAXP:
579: #endif
1.1 misho 580: {
581: char ppphook[NG_HOOKSIZ];
582: char *linkname, *rest;
583: int id;
584:
585: /* Check hook name prefix */
586: linkname = ((struct ngpppoe_sts *)u.resp.data)->hook;
587: if (strncmp(linkname, "listen-", 7) == 0)
588: return; /* We do not need them */
589: snprintf(ppphook, NG_HOOKSIZ, "mpd%d-", gPid);
590: if (strncmp(linkname, ppphook, strlen(ppphook))) {
591: Log(LG_ERR, ("PPPoE: message %d from unknown hook \"%s\"",
592: u.resp.header.cmd, ((struct ngpppoe_sts *)u.resp.data)->hook));
593: return;
594: }
595: linkname += strlen(ppphook);
596: id = strtol(linkname, &rest, 10);
597: if (rest[0] != 0 ||
598: !gLinks[id] ||
599: gLinks[id]->type != &gPppoePhysType ||
600: PIf != ((PppoeInfo)gLinks[id]->info)->PIf) {
601: Log((u.resp.header.cmd == NGM_PPPOE_SUCCESS)?LG_ERR:LG_PHYS,
602: ("PPPoE: message %d from unexisting link \"%s\"",
603: u.resp.header.cmd, linkname));
604: return;
605: }
606:
607: l = gLinks[id];
608: pi = (PppoeInfo)l->info;
609:
610: if (l->state == PHYS_STATE_DOWN) {
611: if (u.resp.header.cmd != NGM_PPPOE_CLOSE)
612: Log(LG_PHYS, ("[%s] PPPoE: message %d in DOWN state",
613: l->name, u.resp.header.cmd));
614: return;
615: }
616: }
617: }
618:
619: /* Decode message. */
620: switch (u.resp.header.cmd) {
621: case NGM_PPPOE_SESSIONID: /* XXX: I do not know what to do with this? */
1.1.1.3 misho 622: Log(LG_PHYS3, ("PPPoE: rec'd SESSIONID %u from \"%s\"",
1.1.1.5.2.1! misho 623: ntohs(*(uint16_t*)u.resp.data), path));
1.1 misho 624: break;
625: case NGM_PPPOE_SUCCESS:
626: Log(LG_PHYS, ("[%s] PPPoE: connection successful", l->name));
627: if (pi->opened) {
628: TimerStop(&pi->connectTimer);
629: l->state = PHYS_STATE_UP;
630: PhysUp(l);
631: } else {
632: l->state = PHYS_STATE_READY;
633: }
634: break;
635: case NGM_PPPOE_FAIL:
636: Log(LG_PHYS, ("[%s] PPPoE: connection failed", l->name));
637: PppoeDoClose(l);
638: PhysDown(l, STR_CON_FAILED0, NULL);
639: break;
640: case NGM_PPPOE_CLOSE:
641: Log(LG_PHYS, ("[%s] PPPoE: connection closed", l->name));
642: PppoeDoClose(l);
643: PhysDown(l, STR_DROPPED, NULL);
644: break;
645: case NGM_PPPOE_ACNAME:
646: Log(LG_PHYS, ("PPPoE: rec'd ACNAME \"%s\"",
647: ((struct ngpppoe_sts *)u.resp.data)->hook));
648: break;
1.1.1.3 misho 649: #ifdef NGM_PPPOE_SETMAXP_COOKIE
650: case NGM_PPPOE_SETMAXP:
651: {
652: struct ngpppoe_maxp *maxp;
653:
1.1.1.5 misho 654: maxp = ((struct ngpppoe_maxp *)(void *)u.resp.data);
1.1.1.3 misho 655: Log(LG_PHYS, ("[%s] PPPoE: rec'd PPP-Max-Payload '%u'",
656: l->name, maxp->data));
657: if (pi->max_payload > 0) {
658: if (pi->max_payload == maxp->data)
659: pi->mp_reply = 1;
660: else
661: Log(LG_PHYS,
662: ("[%s] PPPoE: sent and returned values are not equal",
663: l->name));
664: } else
665: Log(LG_PHYS, ("[%s] PPPoE: server sent tag PPP-Max-Payload"
666: " without request from the client",
667: l->name));
668: break;
669: }
670: #endif
1.1.1.4 misho 671: #ifdef NGM_PPPOE_PADM_COOKIE
672: case NGM_PPPOE_HURL:
673: Log(LG_PHYS, ("PPPoE: rec'd HURL \"%s\"",
674: ((struct ngpppoe_padm *)u.resp.data)->msg));
675: break;
676: case NGM_PPPOE_MOTM:
677: Log(LG_PHYS, ("PPPoE: rec'd MOTM \"%s\"",
678: ((struct ngpppoe_padm *)u.resp.data)->msg));
679: break;
680: #endif
1.1 misho 681: default:
682: Log(LG_PHYS, ("PPPoE: rec'd command %lu from \"%s\"",
683: (u_long)u.resp.header.cmd, path));
684: break;
685: }
686: }
687:
688: /*
689: * PppoeStat()
690: */
691: void
692: PppoeStat(Context ctx)
693: {
694: const PppoeInfo pe = (PppoeInfo)ctx->lnk->info;
695: char buf[32];
696:
1.1.1.3 misho 697: switch (pe->mac_format) {
698: case MAC_UNFORMATTED:
699: sprintf(buf, "unformatted");
700: break;
701: case MAC_UNIX_LIKE:
702: sprintf(buf, "unix-like");
703: break;
704: case MAC_CISCO_LIKE:
705: sprintf(buf, "cisco-like");
706: break;
707: case MAC_IETF:
708: sprintf(buf, "ietf");
709: break;
710: default:
711: sprintf(buf, "unknown");
712: break;
713: }
714:
1.1 misho 715: Printf("PPPoE configuration:\r\n");
1.1.1.4 misho 716: Printf("\tIface Name : %s\r\n", pe->iface);
1.1 misho 717: Printf("\tIface Node : %s\r\n", pe->path);
718: Printf("\tIface Hook : %s\r\n", pe->hook);
719: Printf("\tSession : %s\r\n", pe->session);
1.1.1.3 misho 720: #ifdef NGM_PPPOE_SETMAXP_COOKIE
721: Printf("\tMax-Payload : %u\r\n", pe->max_payload);
722: #endif
723: Printf("\tMAC format : %s\r\n", buf);
1.1 misho 724: Printf("PPPoE status:\r\n");
725: if (ctx->lnk->state != PHYS_STATE_DOWN) {
726: Printf("\tOpened : %s\r\n", (pe->opened?"YES":"NO"));
727: Printf("\tIncoming : %s\r\n", (pe->incoming?"YES":"NO"));
728: PppoePeerMacAddr(ctx->lnk, buf, sizeof(buf));
729: Printf("\tCurrent peer : %s\r\n", buf);
730: Printf("\tSession : %s\r\n", pe->real_session);
1.1.1.3 misho 731: Printf("\tMax-Payload : %s\r\n", (pe->mp_reply?"YES":"NO"));
1.1 misho 732: Printf("\tCircuit-ID : %s\r\n", pe->agent_cid);
733: Printf("\tRemote-ID : %s\r\n", pe->agent_rid);
734: }
735: }
736:
737: /*
738: * PppoeOriginated()
739: */
740: static int
741: PppoeOriginated(Link l)
742: {
743: PppoeInfo const pppoe = (PppoeInfo)l->info;
744:
745: return (pppoe->incoming ? LINK_ORIGINATE_REMOTE : LINK_ORIGINATE_LOCAL);
746: }
747:
748: /*
749: * PppoeIsSync()
750: */
751: static int
752: PppoeIsSync(Link l)
753: {
1.1.1.5 misho 754: (void)l;
1.1 misho 755: return (1);
756: }
757:
758: static int
759: PppoePeerMacAddr(Link l, void *buf, size_t buf_len)
760: {
761: PppoeInfo const pppoe = (PppoeInfo)l->info;
762:
1.1.1.5 misho 763: if (buf_len < 18)
764: return (1);
1.1.1.2 misho 765: ether_ntoa_r((struct ether_addr *)pppoe->peeraddr, buf);
1.1 misho 766: return (0);
767: }
768:
769: static int
770: PppoePeerIface(Link l, void *buf, size_t buf_len)
771: {
772: PppoeInfo const pppoe = (PppoeInfo)l->info;
773:
1.1.1.4 misho 774: strlcpy(buf, pppoe->iface, buf_len);
1.1 misho 775: return (0);
776: }
777:
778: static int
779: PppoeCallingNum(Link l, void *buf, size_t buf_len)
780: {
781: PppoeInfo const pppoe = (PppoeInfo)l->info;
782:
783: if (pppoe->incoming) {
1.1.1.3 misho 784: switch (pppoe->mac_format) {
785: case MAC_UNFORMATTED:
786: snprintf(buf, buf_len, "%02x%02x%02x%02x%02x%02x",
787: pppoe->peeraddr[0], pppoe->peeraddr[1], pppoe->peeraddr[2],
788: pppoe->peeraddr[3], pppoe->peeraddr[4], pppoe->peeraddr[5]);
789: break;
790: case MAC_UNIX_LIKE:
791: ether_ntoa_r((struct ether_addr *)pppoe->peeraddr, buf);
792: break;
793: case MAC_CISCO_LIKE:
794: snprintf(buf, buf_len, "%02x%02x.%02x%02x.%02x%02x",
795: pppoe->peeraddr[0], pppoe->peeraddr[1], pppoe->peeraddr[2],
796: pppoe->peeraddr[3], pppoe->peeraddr[4], pppoe->peeraddr[5]);
797: break;
798: case MAC_IETF:
799: snprintf(buf, buf_len, "%02x-%02x-%02x-%02x-%02x-%02x",
800: pppoe->peeraddr[0], pppoe->peeraddr[1], pppoe->peeraddr[2],
801: pppoe->peeraddr[3], pppoe->peeraddr[4], pppoe->peeraddr[5]);
802: break;
803: default:
804: sprintf(buf, "unknown");
805: return(-1);
806: break;
807: }
1.1 misho 808: } else {
809: strlcpy(buf, pppoe->real_session, buf_len);
810: }
811:
812: return (0);
813: }
814:
815: static int
816: PppoeCalledNum(Link l, void *buf, size_t buf_len)
817: {
818: PppoeInfo const pppoe = (PppoeInfo)l->info;
819:
820: if (!pppoe->incoming) {
1.1.1.3 misho 821: switch (pppoe->mac_format) {
822: case MAC_UNFORMATTED:
823: snprintf(buf, buf_len, "%02x%02x%02x%02x%02x%02x",
824: pppoe->peeraddr[0], pppoe->peeraddr[1], pppoe->peeraddr[2],
825: pppoe->peeraddr[3], pppoe->peeraddr[4], pppoe->peeraddr[5]);
826: break;
827: case MAC_UNIX_LIKE:
828: ether_ntoa_r((struct ether_addr *)pppoe->peeraddr, buf);
829: break;
830: case MAC_CISCO_LIKE:
831: snprintf(buf, buf_len, "%02x%02x.%02x%02x.%02x%02x",
832: pppoe->peeraddr[0], pppoe->peeraddr[1], pppoe->peeraddr[2],
833: pppoe->peeraddr[3], pppoe->peeraddr[4], pppoe->peeraddr[5]);
834: break;
835: case MAC_IETF:
836: snprintf(buf, buf_len, "%02x-%02x-%02x-%02x-%02x-%02x",
837: pppoe->peeraddr[0], pppoe->peeraddr[1], pppoe->peeraddr[2],
838: pppoe->peeraddr[3], pppoe->peeraddr[4], pppoe->peeraddr[5]);
839: break;
840: default:
841: sprintf(buf, "unknown");
842: return(-1);
843: break;
844: }
1.1 misho 845: } else {
846: strlcpy(buf, pppoe->real_session, buf_len);
847: }
848:
849: return (0);
850: }
851:
852: static int
853: PppoeSelfName(Link l, void *buf, size_t buf_len)
854: {
855: PppoeInfo const pppoe = (PppoeInfo)l->info;
856:
857: strlcpy(buf, pppoe->agent_cid, buf_len);
858:
859: return (0);
860: }
861:
862: static int
863: PppoePeerName(Link l, void *buf, size_t buf_len)
864: {
865: PppoeInfo const pppoe = (PppoeInfo)l->info;
866:
867: strlcpy(buf, pppoe->agent_rid, buf_len);
868:
869: return (0);
870: }
871:
1.1.1.3 misho 872: static u_short
873: PppoeGetMtu(Link l, int conf)
874: {
875: PppoeInfo const pppoe = (PppoeInfo)l->info;
876:
877: if (pppoe->max_payload > 0 && pppoe->mp_reply > 0)
878: return (pppoe->max_payload);
879: else
880: if (conf == 0)
881: return (l->type->mtu);
882: else
1.1.1.5.2.1! misho 883: return (l->conf.mtu ? l->conf.mtu : PPPOE_MTU);
1.1.1.3 misho 884: }
885:
886: static u_short
887: PppoeGetMru(Link l, int conf)
888: {
889: PppoeInfo const pppoe = (PppoeInfo)l->info;
890:
891: if (pppoe->max_payload > 0 && pppoe->mp_reply > 0)
892: return (pppoe->max_payload);
893: else
894: if (conf == 0)
895: return (l->type->mru);
896: else
897: return (l->conf.mru);
898: }
899:
1.1 misho 900: static int
1.1.1.4 misho 901: CreatePppoeNode(struct PppoeIf *PIf, const char *iface, const char *path, const char *hook)
1.1 misho 902: {
903: union {
904: u_char buf[sizeof(struct ng_mesg) + 2048];
905: struct ng_mesg reply;
906: } u;
907: struct ng_mesg *resp;
908: const struct hooklist *hlist;
909: const struct nodeinfo *ninfo;
1.1.1.3 misho 910: uint32_t f;
1.1 misho 911:
912: /* Make sure interface is up. */
1.1.1.5 misho 913: if (IfaceSetFlag(iface, IFF_UP) != 0) {
914: Perror("[%s] PPPoE: can't bring up interface", iface);
1.1 misho 915: return (0);
916: }
917: /* Create a new netgraph node */
918: if (NgMkSockNode(NULL, &PIf->csock, &PIf->dsock) < 0) {
919: Perror("[%s] PPPoE: can't create ctrl socket", iface);
1.1.1.5 misho 920: return (0);
1.1 misho 921: }
922: (void)fcntl(PIf->csock, F_SETFD, 1);
923: (void)fcntl(PIf->dsock, F_SETFD, 1);
924:
925: /* Check if NG_ETHER_NODE_TYPE is available. */
926: if (gNgEtherLoaded == FALSE) {
927: const struct typelist *tlist;
928:
929: /* Ask for a list of available node types. */
930: if (NgSendMsg(PIf->csock, "", NGM_GENERIC_COOKIE, NGM_LISTTYPES,
931: NULL, 0) < 0) {
932: Perror("[%s] PPPoE: Cannot send a netgraph message",
933: iface);
934: close(PIf->csock);
935: close(PIf->dsock);
936: return (0);
937: }
938:
939: /* Get response. */
940: resp = &u.reply;
941: if (NgRecvMsg(PIf->csock, resp, sizeof(u.buf), NULL) <= 0) {
942: Perror("[%s] PPPoE: Cannot get netgraph response",
943: iface);
944: close(PIf->csock);
945: close(PIf->dsock);
946: return (0);
947: }
948:
949: /* Look for NG_ETHER_NODE_TYPE. */
1.1.1.5 misho 950: tlist = (const struct typelist*)(void *)resp->data;
1.1 misho 951: for (f = 0; f < tlist->numtypes; f++)
952: if (strncmp(tlist->typeinfo[f].type_name,
953: NG_ETHER_NODE_TYPE,
954: sizeof(NG_ETHER_NODE_TYPE) - 1) == 0)
955: gNgEtherLoaded = TRUE;
956:
957: /* If not found try to load ng_ether and repeat the check. */
958: if (gNgEtherLoaded == FALSE && (kldload("ng_ether") < 0)) {
959: Perror("PPPoE: Cannot load ng_ether");
960: close(PIf->csock);
961: close(PIf->dsock);
962: assert (0);
963: }
964: gNgEtherLoaded = TRUE;
965: }
966:
967: /*
968: * Ask for a list of hooks attached to the "ether" node. This node
969: * should magically exist as a way of hooking stuff onto an ethernet
970: * device.
971: */
972: if (NgSendMsg(PIf->csock, path, NGM_GENERIC_COOKIE, NGM_LISTHOOKS,
973: NULL, 0) < 0) {
974: Perror("[%s] Cannot send a netgraph message: %s", iface, path);
975: close(PIf->csock);
976: close(PIf->dsock);
977: return (0);
978: }
979:
980: /* Get our list back. */
981: resp = &u.reply;
982: if (NgRecvMsg(PIf->csock, resp, sizeof(u.buf), NULL) <= 0) {
983: Perror("[%s] Cannot get netgraph response", iface);
984: close(PIf->csock);
985: close(PIf->dsock);
986: return (0);
987: }
988:
1.1.1.5 misho 989: hlist = (const struct hooklist *)(void *)resp->data;
1.1 misho 990: ninfo = &hlist->nodeinfo;
991:
992: /* Make sure we've got the right type of node. */
993: if (strncmp(ninfo->type, NG_ETHER_NODE_TYPE,
994: sizeof(NG_ETHER_NODE_TYPE) - 1)) {
995: Log(LG_ERR, ("[%s] Unexpected node type ``%s'' (wanted ``"
996: NG_ETHER_NODE_TYPE "'') on %s",
997: iface, ninfo->type, path));
998: close(PIf->csock);
999: close(PIf->dsock);
1000: return (0);
1001: }
1002:
1003: /* Look for a hook already attached. */
1004: for (f = 0; f < ninfo->hooks; f++) {
1005: const struct linkinfo *nlink = &hlist->link[f];
1006:
1007: /* Search for "orphans" hook. */
1008: if (strcmp(nlink->ourhook, NG_ETHER_HOOK_ORPHAN) &&
1009: strcmp(nlink->ourhook, NG_ETHER_HOOK_DIVERT))
1010: continue;
1011:
1012: /*
1013: * Something is using the data coming out of this ``ether''
1014: * node. If it's a PPPoE node, we use that node, otherwise
1015: * we complain that someone else is using the node.
1016: */
1017: if (strcmp(nlink->nodeinfo.type, NG_PPPOE_NODE_TYPE)) {
1018: Log(LG_ERR, ("%s Node type ``%s'' is currently "
1019: " using orphan hook\n",
1020: path, nlink->nodeinfo.type));
1021: close(PIf->csock);
1022: close(PIf->dsock);
1023: return (0);
1024: }
1025: PIf->node_id = nlink->nodeinfo.id;
1026: break;
1027: }
1028:
1029: if (f == ninfo->hooks) {
1030: struct ngm_mkpeer mp;
1031: char path2[NG_PATHSIZ];
1032:
1033: /* Create new PPPoE node. */
1034: memset(&mp, 0, sizeof(mp));
1035: strcpy(mp.type, NG_PPPOE_NODE_TYPE);
1036: strlcpy(mp.ourhook, hook, sizeof(mp.ourhook));
1037: strcpy(mp.peerhook, NG_PPPOE_HOOK_ETHERNET);
1038: if (NgSendMsg(PIf->csock, path, NGM_GENERIC_COOKIE, NGM_MKPEER, &mp,
1039: sizeof(mp)) < 0) {
1040: Perror("[%s] can't create %s peer to %s,%s",
1041: iface, NG_PPPOE_NODE_TYPE, path, hook);
1042: close(PIf->csock);
1043: close(PIf->dsock);
1044: return (0);
1045: }
1046:
1047: snprintf(path2, sizeof(path2), "%s%s", path, hook);
1048: /* Get pppoe node ID */
1049: if ((PIf->node_id = NgGetNodeID(PIf->csock, path2)) == 0) {
1.1.1.5 misho 1050: Perror("[%s] Cannot get %s node id", iface,
1051: NG_PPPOE_NODE_TYPE);
1.1 misho 1052: close(PIf->csock);
1053: close(PIf->dsock);
1054: return (0);
1055: };
1056: };
1057:
1058: /* Register an event listening to the control and data sockets. */
1059: EventRegister(&(PIf->ctrlEvent), EVENT_READ, PIf->csock,
1060: EVENT_RECURRING, PppoeCtrlReadEvent, PIf);
1061: EventRegister(&(PIf->dataEvent), EVENT_READ, PIf->dsock,
1062: EVENT_RECURRING, PppoeListenEvent, PIf);
1063:
1064: return (1);
1065: }
1066:
1067: /*
1068: * Look for a tag of a specific type.
1069: * Don't trust any length the other end says,
1070: * but assume we already sanity checked ph->length.
1071: */
1072: static const struct pppoe_tag*
1073: get_tag(const struct pppoe_hdr* ph, uint16_t idx)
1074: {
1075: const char *const end = ((const char *)(ph + 1))
1076: + ntohs(ph->length);
1077: const struct pppoe_tag *pt = (const void *)(ph + 1);
1078: const char *ptn;
1079:
1080: /*
1081: * Keep processing tags while a tag header will still fit.
1082: */
1083: while((const char*)(pt + 1) <= end) {
1084: /*
1085: * If the tag data would go past the end of the packet, abort.
1086: */
1087: ptn = (((const char *)(pt + 1)) + ntohs(pt->tag_len));
1088: if (ptn > end)
1089: return (NULL);
1090: if (pt->tag_type == idx)
1091: return (pt);
1092:
1093: pt = (const struct pppoe_tag*)ptn;
1094: }
1095:
1096: return (NULL);
1097: }
1098:
1099: static const struct pppoe_tag*
1100: get_vs_tag(const struct pppoe_hdr* ph, uint32_t idx)
1101: {
1102: const char *const end = ((const char *)(ph + 1))
1103: + ntohs(ph->length);
1104: const struct pppoe_tag *pt = (const void *)(ph + 1);
1105: const char *ptn;
1106:
1107: /*
1108: * Keep processing tags while a tag header will still fit.
1109: */
1110: while((const char*)(pt + 1) <= end) {
1111: /*
1112: * If the tag data would go past the end of the packet, abort.
1113: */
1114: ptn = (((const char *)(pt + 1)) + ntohs(pt->tag_len));
1115: if (ptn > end)
1116: return (NULL);
1117: if (pt->tag_type == PTT_VENDOR &&
1118: ntohs(pt->tag_len) >= 4 &&
1.1.1.5 misho 1119: *(const uint32_t*)(const void *)(pt + 1) == idx)
1.1 misho 1120: return (pt);
1121:
1122: pt = (const struct pppoe_tag*)ptn;
1123: }
1124:
1125: return (NULL);
1126: }
1127:
1128: static void
1.1.1.3 misho 1129: print_tags(const struct pppoe_hdr* ph)
1130: {
1131: const char *const end = ((const char *)(ph + 1))
1132: + ntohs(ph->length);
1133: const struct pppoe_tag *pt = (const void *)(ph + 1);
1134: const char *ptn;
1135: const void *v;
1136: char buf[1024], tag[32];
1137: size_t len, k;
1138:
1139: /*
1140: * Keep processing tags while a tag header will still fit.
1141: */
1142: while((const char*)(pt + 1) <= end) {
1143: /*
1144: * If the tag data would go past the end of the packet, abort.
1145: */
1146: v = pt + 1;
1147: ptn = (((const char *)(pt + 1)) + ntohs(pt->tag_len));
1148: if (ptn > end)
1149: return;
1150: len = ntohs(pt->tag_len);
1151: buf[0] = 0;
1152: switch (pt->tag_type) {
1153: case PTT_EOL:
1154: if (len != 0)
1155: sprintf(buf, "TAG_LENGTH is not zero!");
1156: break;
1157: case PTT_SRV_NAME:
1158: if (len >= sizeof(buf))
1159: len = sizeof(buf)-1;
1160: memcpy(buf, pt + 1, len);
1161: buf[len] = 0;
1162: if (len == 0)
1163: sprintf(buf, "Any service is acceptable");
1164: break;
1165: case PTT_AC_NAME:
1166: if (len >= sizeof(buf))
1167: len = sizeof(buf)-1;
1168: memcpy(buf, pt + 1, len);
1169: buf[len] = 0;
1170: break;
1171: case PTT_HOST_UNIQ:
1172: case PTT_AC_COOKIE:
1173: case PTT_RELAY_SID:
1174: snprintf(buf, sizeof(buf), "0x%s", Bin2Hex(v, len));
1175: break;
1176: case PTT_VENDOR:
1177: if (len >= 4) {
1.1.1.5 misho 1178: if ((const uint8_t)*(const uint8_t*)v != 0) {
1.1.1.3 misho 1179: snprintf(buf, sizeof(buf),
1180: "First byte of VENDOR is not zero! 0x%s",
1181: Bin2Hex(v, len));
1182: } else {
1183: snprintf(buf, sizeof(buf), "0x%s 0x%s",
1184: Bin2Hex(v, 4),
1185: Bin2Hex((const uint8_t*)v + 4, len - 4));
1186: }
1187: } else {
1188: sprintf(buf, "TAG_LENGTH must be >= 4 !");
1189: }
1190: break;
1191: case PTT_MAX_PAYL:
1192: if (len != 2) {
1193: sprintf(buf, "TAG_LENGTH is not 2!");
1194: } else {
1.1.1.5 misho 1195: sprintf(buf, "%u", *(const uint16_t*)(const void *)(pt + 1));
1.1.1.3 misho 1196: }
1197: break;
1198: case PTT_SRV_ERR:
1199: if (len > 0 && (const char *)(pt + 1)+4 !=0) {
1200: if (len >= sizeof(buf))
1201: len = sizeof(buf)-1;
1202: memcpy(buf, pt + 1, len);
1203: buf[len] = 0;
1204: }
1205: break;
1206: case PTT_SYS_ERR:
1207: case PTT_GEN_ERR:
1208: if (len >= sizeof(buf))
1209: len = sizeof(buf)-1;
1210: memcpy(buf, pt + 1, len);
1211: buf[len] = 0;
1212: break;
1213: case MPD_PTT_CREDITS:
1214: case MPD_PTT_METRICS:
1215: case MPD_PTT_SEQ_NUMBER:
1216: case MPD_PTT_HURL:
1217: case MPD_PTT_MOTM:
1218: case MPD_PTT_IP_ROUTE_ADD:
1219: sprintf(buf, "Not implemented");
1220: break;
1221: default:
1222: sprintf(buf, "0x%04x", pt->tag_type);
1223: break;
1224: }
1225: /* First check our stat list for known tags */
1226: for (k = 0; k < NUM_TAG_NAMES; k++) {
1227: if (pt->tag_type == tag2str[k].tag) {
1228: sprintf(tag, "%s", tag2str[k].name);
1229: break;
1230: }
1231: }
1232: Log(LG_PHYS3, ("TAG: %s, Value: %s", tag, buf));
1233: pt = (const struct pppoe_tag*)ptn;
1234: }
1235: }
1236:
1237: static void
1.1 misho 1238: PppoeListenEvent(int type, void *arg)
1239: {
1240: int k, sz;
1241: struct PppoeIf *PIf = (struct PppoeIf *)(arg);
1242: char rhook[NG_HOOKSIZ];
1243: unsigned char response[1024];
1244:
1245: char path[NG_PATHSIZ];
1246: char path1[NG_PATHSIZ];
1247: char session_hook[NG_HOOKSIZ];
1248: char *session;
1249: char real_session[MAX_SESSION];
1250: char agent_cid[64];
1251: char agent_rid[64];
1252: struct ngm_connect cn;
1253: struct ngm_mkpeer mp;
1254: Link l = NULL;
1255: PppoeInfo pi = NULL;
1256: const struct pppoe_full_hdr *wh;
1257: const struct pppoe_hdr *ph;
1258: const struct pppoe_tag *tag;
1259:
1.1.1.5.2.1! misho 1260: u_int16_t length;
! 1261:
1.1 misho 1262: union {
1263: u_char buf[sizeof(struct ngpppoe_init_data) + MAX_SESSION];
1264: struct ngpppoe_init_data poeid;
1265: } u;
1266: struct ngpppoe_init_data *const idata = &u.poeid;
1267:
1.1.1.5 misho 1268: (void)type;
1.1 misho 1269: switch (sz = NgRecvData(PIf->dsock, response, sizeof(response), rhook)) {
1270: case -1:
1271: Log(LG_ERR, ("NgRecvData: %d", sz));
1272: return;
1273: case 0:
1274: Log(LG_ERR, ("NgRecvData: socket closed"));
1275: return;
1276: }
1277:
1278: if (strncmp(rhook, "listen-", 7)) {
1279: Log(LG_ERR, ("PPPoE: data from unknown hook \"%s\"", rhook));
1280: return;
1281: }
1282:
1283: session = rhook + 7;
1284:
1.1.1.5 misho 1285: if ((size_t)sz < sizeof(struct pppoe_full_hdr)) {
1.1 misho 1286: Log(LG_PHYS, ("Incoming truncated PPPoE connection request via %s for "
1287: "service \"%s\"", PIf->ifnodepath, session));
1288: return;
1289: }
1290:
1291: wh = (struct pppoe_full_hdr *)response;
1292: ph = &wh->ph;
1.1.1.5.2.1! misho 1293:
! 1294: /* Sanity check */
! 1295: length = ntohs(ph->length);
! 1296: if (length > (size_t)sz - sizeof(struct pppoe_full_hdr)) {
! 1297: Log(LG_PHYS, ("Ignored incoming PPPoE connection request "
! 1298: "via %s for service \"%s\" from %s "
! 1299: "due to bad length %hu > %u",
! 1300: PIf->ifnodepath, session,
! 1301: ether_ntoa((const struct ether_addr *)&wh->eh.ether_shost),
! 1302: length,
! 1303: (unsigned)((size_t)sz - sizeof(struct pppoe_full_hdr))));
! 1304: return;
! 1305: }
! 1306:
1.1 misho 1307: if ((tag = get_tag(ph, PTT_SRV_NAME))) {
1.1.1.5 misho 1308: size_t len = ntohs(tag->tag_len);
1.1 misho 1309: if (len >= sizeof(real_session))
1310: len = sizeof(real_session)-1;
1311: memcpy(real_session, tag + 1, len);
1312: real_session[len] = 0;
1313: } else {
1314: strlcpy(real_session, session, sizeof(real_session));
1315: }
1316: bzero(agent_cid, sizeof(agent_cid));
1317: bzero(agent_rid, sizeof(agent_rid));
1318: if ((tag = get_vs_tag(ph, htonl(0x00000DE9)))) {
1.1.1.5 misho 1319: size_t len = ntohs(tag->tag_len) - 4, pos = 0;
1.1 misho 1320: const char *b = (const char *)(tag + 1) + 4;
1321: while (pos + 1 <= len) {
1.1.1.5 misho 1322: size_t len1 = b[pos + 1];
1.1 misho 1323: if (len1 > len - pos - 2)
1324: break;
1325: if (len1 >= sizeof(agent_rid))
1326: len1 = sizeof(agent_rid) - 1;
1327: switch (b[pos]) {
1328: case 1:
1329: strncpy(agent_cid, &b[pos + 2], len1);
1330: break;
1331: case 2:
1332: strncpy(agent_rid, &b[pos + 2], len1);
1333: break;
1334: }
1335: pos += 2 + len1;
1336: }
1337: }
1.1.1.3 misho 1338:
1.1 misho 1339: Log(LG_PHYS, ("Incoming PPPoE connection request via %s for "
1340: "service \"%s\" from %s", PIf->ifnodepath, real_session,
1.1.1.5 misho 1341: ether_ntoa((const struct ether_addr *)&wh->eh.ether_shost)));
1.1 misho 1342:
1.1.1.3 misho 1343: if (gLogOptions & LG_PHYS3)
1344: print_tags(ph);
1345:
1.1 misho 1346: if (gShutdownInProgress) {
1347: Log(LG_PHYS, ("Shutdown sequence in progress, ignoring request."));
1348: return;
1349: }
1350:
1351: if (OVERLOAD()) {
1352: Log(LG_PHYS, ("Daemon overloaded, ignoring request."));
1353: return;
1354: }
1355:
1356: /* Examine all PPPoE links. */
1357: for (k = 0; k < gNumLinks; k++) {
1358: Link l2;
1359: PppoeInfo pi2;
1360:
1361: if (!gLinks[k] || gLinks[k]->type != &gPppoePhysType)
1362: continue;
1363:
1364: l2 = gLinks[k];
1365: pi2 = (PppoeInfo)l2->info;
1366:
1367: if ((!PhysIsBusy(l2)) &&
1368: (pi2->PIf == PIf) &&
1369: (strcmp(pi2->session, session) == 0) &&
1370: Enabled(&l2->conf.options, LINK_CONF_INCOMING)) {
1371: l = l2;
1372: break;
1373: }
1374: }
1375:
1376: if (l != NULL && l->tmpl)
1377: l = LinkInst(l, NULL, 0, 0);
1378:
1379: if (l == NULL) {
1380: Log(LG_PHYS, ("No free PPPoE link with requested parameters "
1381: "was found"));
1382: return;
1383: }
1384: pi = (PppoeInfo)l->info;
1385:
1386: Log(LG_PHYS, ("[%s] Accepting PPPoE connection", l->name));
1387:
1388: /* Path to the ng_pppoe */
1389: snprintf(path, sizeof(path), "[%x]:", PIf->node_id);
1390:
1391: /* Name of ng_pppoe session hook */
1392: snprintf(session_hook, sizeof(session_hook), "mpd%d-%d",
1393: gPid, l->id);
1394:
1395: /* Create ng_tee(4) node and connect it to ng_pppoe(4). */
1396: memset(&mp, 0, sizeof(mp));
1397: strcpy(mp.type, NG_TEE_NODE_TYPE);
1398: strlcpy(mp.ourhook, session_hook, sizeof(mp.ourhook));
1399: snprintf(mp.peerhook, sizeof(mp.peerhook), "left");
1400: if (NgSendMsg(pi->PIf->csock, path, NGM_GENERIC_COOKIE, NGM_MKPEER,
1401: &mp, sizeof(mp)) < 0) {
1402: Perror("[%s] PPPoE: can't create %s peer to %s,%s",
1403: l->name, NG_TEE_NODE_TYPE, path, "left");
1404: goto close_socket;
1405: }
1406:
1407: /* Path to the ng_tee */
1408: snprintf(path1, sizeof(path), "%s%s", path, session_hook);
1409:
1410: /* Connect our socket node link hook to the ng_tee(4) node. */
1411: memset(&cn, 0, sizeof(cn));
1412: strlcpy(cn.ourhook, l->name, sizeof(cn.ourhook));
1413: strlcpy(cn.path, path1, sizeof(cn.path));
1414: strcpy(cn.peerhook, "left2right");
1415: if (NgSendMsg(pi->PIf->csock, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT,
1416: &cn, sizeof(cn)) < 0) {
1417: Perror("[%s] PPPoE: can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
1418: l->name, ".:", cn.ourhook, cn.path, cn.peerhook);
1419: goto shutdown_tee;
1420: }
1421:
1422: /* Put the PPPoE node into OFFER mode. */
1423: memset(idata, 0, sizeof(*idata));
1424: strlcpy(idata->hook, session_hook, sizeof(idata->hook));
1425: if (pi->acname[0] != 0) {
1426: strlcpy(idata->data, pi->acname, MAX_SESSION);
1427: } else {
1428: if (gethostname(idata->data, MAX_SESSION) == -1) {
1429: Log(LG_ERR, ("[%s] PPPoE: gethostname() failed",
1430: l->name));
1431: idata->data[0] = 0;
1432: }
1433: if (idata->data[0] == 0)
1434: strlcpy(idata->data, "NONAME", MAX_SESSION);
1435: }
1436: idata->data_len=strlen(idata->data);
1437:
1438: if (NgSendMsg(pi->PIf->csock, path, NGM_PPPOE_COOKIE, NGM_PPPOE_OFFER,
1439: idata, sizeof(*idata) + idata->data_len) < 0) {
1440: Perror("[%s] PPPoE: can't send NGM_PPPOE_OFFER to %s,%s ",
1441: l->name, path, idata->hook);
1442: goto shutdown_tee;
1443: }
1444:
1445: memset(idata, 0, sizeof(*idata));
1446: strlcpy(idata->hook, session_hook, sizeof(idata->hook));
1447: idata->data_len = strlen(pi->session);
1448: strncpy(idata->data, pi->session, MAX_SESSION);
1449:
1450: if (NgSendMsg(pi->PIf->csock, path, NGM_PPPOE_COOKIE,
1451: NGM_PPPOE_SERVICE, idata,
1452: sizeof(*idata) + idata->data_len) < 0) {
1453: Perror("[%s] PPPoE: can't send NGM_PPPOE_SERVICE to %s,%s",
1454: l->name, path, idata->hook);
1455: goto shutdown_tee;
1456: }
1457:
1458: /* And send our request data to the waiting node. */
1459: if (NgSendData(pi->PIf->dsock, l->name, response, sz) == -1) {
1460: Perror("[%s] PPPoE: Cannot send original request", l->name);
1461: goto shutdown_tee;
1462: }
1463:
1464: if (NgFuncDisconnect(pi->PIf->csock, l->name, ".:", l->name) < 0) {
1465: Perror("[%s] PPPoE: can't remove hook %s", l->name, l->name);
1466: goto shutdown_tee;
1467: }
1468: l->state = PHYS_STATE_CONNECTING;
1469: pi->incoming = 1;
1470: /* Record the peer's MAC address */
1471: memcpy(pi->peeraddr, wh->eh.ether_shost, 6);
1472: strlcpy(pi->real_session, real_session, sizeof(pi->real_session));
1473: strlcpy(pi->agent_cid, agent_cid, sizeof(pi->agent_cid));
1474: strlcpy(pi->agent_rid, agent_rid, sizeof(pi->agent_rid));
1475:
1476: Log(LG_PHYS2, ("[%s] PPPoE response sent", l->name));
1477:
1478: /* Set a timer to limit connection time. */
1479: TimerInit(&pi->connectTimer, "PPPoE-connect",
1480: PPPOE_CONNECT_TIMEOUT * SECONDS, PppoeConnectTimeout, l);
1481: TimerStart(&pi->connectTimer);
1482:
1483: PhysIncoming(l);
1484: return;
1485:
1486: shutdown_tee:
1487: if (NgFuncShutdownNode(pi->PIf->csock, l->name, path1) < 0) {
1488: Perror("[%s] Shutdown ng_tee node %s error", l->name, path1);
1489: };
1490:
1491: close_socket:
1492: Log(LG_PHYS, ("[%s] PPPoE connection not accepted due to error",
1493: l->name));
1494:
1495: /* If link is not static - shutdown it. */
1496: if (!l->stay)
1497: LinkShutdown(l);
1498: }
1499:
1500: /*
1501: * PppoeGetNode()
1502: */
1503:
1504: static void
1505: PppoeGetNode(Link l)
1506: {
1507: int i, j = -1, free = -1;
1508: PppoeInfo pi = (PppoeInfo)l->info;
1509:
1510: if (pi->PIf) // Do this only once for interface
1511: return;
1512:
1513: if (!strcmp(pi->path, "undefined:")) {
1514: Log(LG_ERR, ("[%s] PPPoE: Skipping link \"%s\" with undefined "
1515: "interface", l->name, l->name));
1516: return;
1517: }
1518:
1519: for (i = 0; i < PPPOE_MAXPARENTIFS; i++) {
1520: if (PppoeIfs[i].ifnodepath[0] == 0) {
1521: free = i;
1522: } else if (strcmp(PppoeIfs[i].ifnodepath, pi->path) == 0) {
1523: j = i;
1524: break;
1525: }
1526: }
1527: if (j == -1) {
1528: if (free == -1) {
1529: Log(LG_ERR, ("[%s] PPPoE: Too many different parent interfaces! ",
1530: l->name));
1531: return;
1532: }
1.1.1.4 misho 1533: if (CreatePppoeNode(&PppoeIfs[free], pi->iface, pi->path, pi->hook)) {
1.1 misho 1534: strlcpy(PppoeIfs[free].ifnodepath,
1535: pi->path,
1536: sizeof(PppoeIfs[free].ifnodepath));
1537: PppoeIfs[free].refs = 1;
1538: pi->PIf = &PppoeIfs[free];
1539: } else {
1540: Log(LG_ERR, ("[%s] PPPoE: Error creating ng_pppoe "
1541: "node on %s", l->name, pi->path));
1542: return;
1543: }
1544: } else {
1545: PppoeIfs[j].refs++;
1546: pi->PIf = &PppoeIfs[j];
1547: }
1548: }
1549:
1550: /*
1551: * PppoeReleaseNode()
1552: */
1553:
1554: static void
1555: PppoeReleaseNode(Link l)
1556: {
1557: PppoeInfo pi = (PppoeInfo)l->info;
1558:
1559: if (!pi->PIf) // Do this only once for interface
1560: return;
1561:
1562: pi->PIf->refs--;
1563: if (pi->PIf->refs == 0) {
1564: pi->PIf->ifnodepath[0] = 0;
1565: pi->PIf->node_id = 0;
1566: EventUnRegister(&pi->PIf->ctrlEvent);
1567: EventUnRegister(&pi->PIf->dataEvent);
1568: close(pi->PIf->csock);
1569: pi->PIf->csock = -1;
1570: close(pi->PIf->dsock);
1571: pi->PIf->dsock = -1;
1572: }
1573:
1574: pi->PIf = NULL;
1575: }
1576:
1577: static int
1578: PppoeListen(Link l)
1579: {
1580: PppoeInfo pi = (PppoeInfo)l->info;
1581: struct PppoeIf *PIf = pi->PIf;
1582: struct PppoeList *pl;
1583: union {
1584: u_char buf[sizeof(struct ngpppoe_init_data) + MAX_SESSION];
1585: struct ngpppoe_init_data poeid;
1586: } u;
1587: struct ngpppoe_init_data *const idata = &u.poeid;
1588: char path[NG_PATHSIZ];
1589: struct ngm_connect cn;
1590:
1591: if (pi->list || !pi->PIf)
1592: return(1); /* Do this only once */
1593:
1594: SLIST_FOREACH(pl, &pi->PIf->list, next) {
1595: if (strcmp(pl->session, pi->session) == 0)
1596: break;
1597: }
1598: if (pl) {
1599: pl->refs++;
1600: pi->list = pl;
1601: return (1);
1602: }
1603:
1604: pl = Malloc(MB_PHYS, sizeof(*pl));
1605: strlcpy(pl->session, pi->session, sizeof(pl->session));
1606: pl->refs = 1;
1607: pi->list = pl;
1608: SLIST_INSERT_HEAD(&pi->PIf->list, pl, next);
1609:
1610: snprintf(path, sizeof(path), "[%x]:", PIf->node_id);
1611:
1612: /* Connect our socket node link hook to the ng_pppoe(4) node. */
1613: memset(&cn, 0, sizeof(cn));
1614: strcpy(cn.path, path);
1615: snprintf(cn.ourhook, sizeof(cn.peerhook), "listen-%s", pi->session);
1616: strcpy(cn.peerhook, cn.ourhook);
1617:
1618: if (NgSendMsg(PIf->csock, ".:", NGM_GENERIC_COOKIE, NGM_CONNECT, &cn,
1619: sizeof(cn)) < 0) {
1.1.1.3 misho 1620: Perror("PPPoE: Can't connect \"%s\"->\"%s\" and \"%s\"->\"%s\"",
1621: ".:", cn.ourhook, cn.path, cn.peerhook);
1.1 misho 1622: return(0);
1623: }
1624:
1625: /* Tell the PPPoE node to be a server. */
1626: memset(idata, 0, sizeof(*idata));
1627: snprintf(idata->hook, sizeof(idata->hook), "listen-%s", pi->session);
1628: idata->data_len = strlen(pi->session);
1629: strncpy(idata->data, pi->session, MAX_SESSION);
1630:
1631: if (NgSendMsg(PIf->csock, path, NGM_PPPOE_COOKIE, NGM_PPPOE_LISTEN,
1632: idata, sizeof(*idata) + idata->data_len) < 0) {
1633: Perror("PPPoE: Can't send NGM_PPPOE_LISTEN to %s hook %s",
1634: path, idata->hook);
1635: return (0);
1636: }
1637:
1638: Log(LG_PHYS, ("PPPoE: waiting for connection on %s, service \"%s\"",
1639: PIf->ifnodepath, idata->data));
1640:
1641: return (1);
1642: }
1643:
1644: static int
1645: PppoeUnListen(Link l)
1646: {
1647: PppoeInfo pi = (PppoeInfo)l->info;
1648: struct PppoeIf *PIf = pi->PIf;
1649: char path[NG_PATHSIZ];
1650: char session_hook[NG_HOOKSIZ];
1651:
1652: if (!pi->list)
1653: return(1); /* Do this only once */
1654:
1655: pi->list->refs--;
1656:
1657: if (pi->list->refs == 0) {
1658:
1659: snprintf(path, sizeof(path), "[%x]:", pi->PIf->node_id);
1660: snprintf(session_hook, sizeof(session_hook), "listen-%s", pi->list->session);
1661: NgFuncDisconnect(pi->PIf->csock, l->name, path, session_hook);
1662:
1663: Log(LG_PHYS, ("PPPoE: stop waiting for connection on %s, service \"%s\"",
1664: PIf->ifnodepath, pi->list->session));
1665:
1666: SLIST_REMOVE(&PIf->list, pi->list, PppoeList, next);
1667: Freee(pi->list);
1668: }
1669:
1670: pi->list = NULL;
1671: return (1);
1672: }
1673:
1674: /*
1675: * PppoeNodeUpdate()
1676: */
1677:
1678: static void
1679: PppoeNodeUpdate(Link l)
1680: {
1681: PppoeInfo pi = (PppoeInfo)l->info;
1682: if (!pi->list) {
1683: if (Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
1684: PppoeGetNode(l);
1685: PppoeListen(l);
1686: }
1687: } else {
1688: if (!Enabled(&l->conf.options, LINK_CONF_INCOMING)) {
1689: PppoeUnListen(l);
1690: if (l->state == PHYS_STATE_DOWN)
1691: PppoeReleaseNode(l);
1692: }
1693: }
1694: }
1695:
1696: /*
1697: * PppoeSetCommand()
1698: */
1699:
1700: static int
1.1.1.5 misho 1701: PppoeSetCommand(Context ctx, int ac, const char *const av[], const void *arg)
1.1 misho 1702: {
1703: const PppoeInfo pi = (PppoeInfo) ctx->lnk->info;
1704: const char *hookname = ETHER_DEFAULT_HOOK;
1.1.1.4 misho 1705: int i;
1.1.1.3 misho 1706: #ifdef NGM_PPPOE_SETMAXP_COOKIE
1707: int ap;
1.1.1.5.2.1! misho 1708: uint16_t mtu;
1.1.1.3 misho 1709: #endif
1.1 misho 1710: switch ((intptr_t)arg) {
1711: case SET_IFACE:
1712: switch (ac) {
1713: case 2:
1714: hookname = av[1];
1715: /* fall through */
1716: case 1:
1.1.1.4 misho 1717: strlcpy(pi->iface, av[0], sizeof(pi->iface));
1718: strlcpy(pi->path, pi->iface, sizeof(pi->path) - 1);
1719: for (i = 0; i < sizeof(pi->path) - 1; i++) {
1720: if (pi->path[i] == '.' || pi->path[i] == ':')
1721: pi->path[i] = '_';
1722: else if (pi->path[i] == '\0') {
1723: pi->path[i] = ':';
1724: pi->path[i + 1] = '\0';
1725: break;
1726: }
1727: }
1.1 misho 1728: strlcpy(pi->hook, hookname, sizeof(pi->hook));
1.1.1.5.2.1! misho 1729:
! 1730: #ifdef NGM_PPPOE_SETMAXP_COOKIE
! 1731: if (pi->max_payload > 0) {
! 1732: mtu = GetSystemIfaceMTU(pi->iface);
! 1733: if (mtu == 0)
! 1734: mtu = ETHER_MAX_LEN;
! 1735: if (pi->max_payload > mtu - 8) {
! 1736: pi->max_payload = mtu - 8;
! 1737: Perror("[%s] PPPoE: PPP-Max-Payload"
! 1738: " value reduced to %hu",
! 1739: pi->iface, pi->max_payload);
! 1740: }
! 1741: }
! 1742: #endif
1.1 misho 1743: break;
1744: default:
1745: return(-1);
1746: }
1747: if (pi->list) {
1748: PppoeUnListen(ctx->lnk);
1749: PppoeReleaseNode(ctx->lnk);
1750: PppoeGetNode(ctx->lnk);
1751: PppoeListen(ctx->lnk);
1752: }
1753: break;
1754: case SET_SESSION:
1755: if (ac != 1)
1756: return(-1);
1757: strlcpy(pi->session, av[0], sizeof(pi->session));
1758: if (pi->list) {
1759: PppoeUnListen(ctx->lnk);
1760: PppoeListen(ctx->lnk);
1761: }
1762: break;
1763: case SET_ACNAME:
1764: if (ac != 1)
1765: return(-1);
1766: strlcpy(pi->acname, av[0], sizeof(pi->acname));
1.1.1.3 misho 1767: break;
1768: #ifdef NGM_PPPOE_SETMAXP_COOKIE
1769: case SET_MAX_PAYLOAD:
1770: if (ac != 1)
1771: return(-1);
1772: ap = atoi(av[0]);
1.1.1.5.2.1! misho 1773: if (pi->iface[0] == '\0') {
! 1774: if (ap < PPPOE_MRU) /* postpone check for MTU */
! 1775: Error("PPP-Max-Payload value \"%s\" less than %d",
! 1776: av[0], PPPOE_MRU);
! 1777: } else {
! 1778: mtu = GetSystemIfaceMTU(pi->iface);
! 1779: if (mtu == 0)
! 1780: mtu = ETHER_MAX_LEN;
! 1781: if (ap < PPPOE_MRU || ap > mtu - 8)
! 1782: Error("PPP-Max-Payload value \"%s\" not in a range of %d..%hu",
! 1783: av[0], PPPOE_MRU, mtu);
! 1784: }
1.1.1.3 misho 1785: pi->max_payload = ap;
1786: break;
1787: #endif
1788: case SET_MAC_FORMAT:
1789: if (ac != 1)
1790: return(-1);
1791: if (strcmp(av[0], "unformatted") == 0) {
1792: pi->mac_format = MAC_UNFORMATTED;
1793: } else if (strcmp(av[0], "unix-like") == 0) {
1794: pi->mac_format = MAC_UNIX_LIKE;
1795: } else if (strcmp(av[0], "cisco-like") == 0) {
1796: pi->mac_format = MAC_CISCO_LIKE;
1797: } else if (strcmp(av[0], "ietf") == 0) {
1798: pi->mac_format = MAC_IETF;
1799: } else {
1800: Error("Incorrect PPPoE mac-format \"%s\"", av[0]);
1801: }
1.1 misho 1802: break;
1803: default:
1804: assert(0);
1805: }
1806: return(0);
1807: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>