Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/ng_pppoe.c
Show First 20 Lines • Show All 169 Lines • ▼ Show 20 Lines | static const struct ng_cmdlist ng_pppoe_cmds[] = { | ||||
}, | }, | ||||
{ | { | ||||
NGM_PPPOE_COOKIE, | NGM_PPPOE_COOKIE, | ||||
NGM_PPPOE_SETMAXP, | NGM_PPPOE_SETMAXP, | ||||
"setmaxp", | "setmaxp", | ||||
&ng_parse_uint16_type, | &ng_parse_uint16_type, | ||||
NULL | NULL | ||||
}, | }, | ||||
{ | |||||
NGM_PPPOE_COOKIE, | |||||
NGM_PPPOE_SEND_HURL, | |||||
"send_hurl", | |||||
&ngpppoe_init_data_state_type, | |||||
NULL | |||||
}, | |||||
{ | |||||
NGM_PPPOE_COOKIE, | |||||
NGM_PPPOE_SEND_MOTM, | |||||
"send_motm", | |||||
&ngpppoe_init_data_state_type, | |||||
NULL | |||||
}, | |||||
{ 0 } | { 0 } | ||||
}; | }; | ||||
/* Netgraph node type descriptor */ | /* Netgraph node type descriptor */ | ||||
static struct ng_type typestruct = { | static struct ng_type typestruct = { | ||||
.version = NG_ABI_VERSION, | .version = NG_ABI_VERSION, | ||||
.name = NG_PPPOE_NODE_TYPE, | .name = NG_PPPOE_NODE_TYPE, | ||||
.constructor = ng_pppoe_constructor, | .constructor = ng_pppoe_constructor, | ||||
Show All 35 Lines | struct sess_neg { | ||||
struct mbuf *m; /* holds cluster with last sent packet */ | struct mbuf *m; /* holds cluster with last sent packet */ | ||||
union packet *pkt; /* points within the above cluster */ | union packet *pkt; /* points within the above cluster */ | ||||
struct callout handle; /* see timeout(9) */ | struct callout handle; /* see timeout(9) */ | ||||
u_int timeout; /* 0,1,2,4,8,16 etc. seconds */ | u_int timeout; /* 0,1,2,4,8,16 etc. seconds */ | ||||
u_int numtags; | u_int numtags; | ||||
const struct pppoe_tag *tags[NUMTAGS]; | const struct pppoe_tag *tags[NUMTAGS]; | ||||
u_int service_len; | u_int service_len; | ||||
u_int ac_name_len; | u_int ac_name_len; | ||||
u_int host_uniq_len; | |||||
struct datatag service; | struct datatag service; | ||||
struct datatag ac_name; | struct datatag ac_name; | ||||
struct datatag host_uniq; | |||||
}; | }; | ||||
typedef struct sess_neg *negp; | typedef struct sess_neg *negp; | ||||
/* | /* | ||||
* Session information that is needed after connection. | * Session information that is needed after connection. | ||||
*/ | */ | ||||
struct sess_con { | struct sess_con { | ||||
hook_p hook; | hook_p hook; | ||||
▲ Show 20 Lines • Show All 344 Lines • ▼ Show 20 Lines | pppoe_findsession(priv_p privp, const struct pppoe_full_hdr *wh) | ||||
return (sp); | return (sp); | ||||
} | } | ||||
static hook_p | static hook_p | ||||
pppoe_finduniq(node_p node, const struct pppoe_tag *tag) | pppoe_finduniq(node_p node, const struct pppoe_tag *tag) | ||||
{ | { | ||||
hook_p hook = NULL; | hook_p hook = NULL; | ||||
union uniq uniq; | sessp sp; | ||||
bcopy(tag + 1, uniq.bytes, sizeof(void *)); | |||||
/* Cycle through all known hooks. */ | /* Cycle through all known hooks. */ | ||||
LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) { | LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) { | ||||
/* Skip any nonsession hook. */ | /* Skip any nonsession hook. */ | ||||
if (NG_HOOK_PRIVATE(hook) == NULL) | if (NG_HOOK_PRIVATE(hook) == NULL) | ||||
continue; | continue; | ||||
if (uniq.pointer == NG_HOOK_PRIVATE(hook)) | sp = NG_HOOK_PRIVATE(hook); | ||||
if (sp->neg->host_uniq_len == ntohs(tag->tag_len) && | |||||
bcmp(sp->neg->host_uniq.data, (const char *)(tag + 1), | |||||
sp->neg->host_uniq_len) == 0) | |||||
break; | break; | ||||
} | } | ||||
CTR3(KTR_NET, "%20s: matched %p for %p", __func__, hook, uniq.pointer); | CTR3(KTR_NET, "%20s: matched %p for %p", __func__, hook, sp); | ||||
return (hook); | return (hook); | ||||
} | } | ||||
static hook_p | |||||
pppoe_findcookie(node_p node, const struct pppoe_tag *tag) | |||||
{ | |||||
hook_p hook = NULL; | |||||
union uniq cookie; | |||||
bcopy(tag + 1, cookie.bytes, sizeof(void *)); | |||||
/* Cycle through all known hooks. */ | |||||
LIST_FOREACH(hook, &node->nd_hooks, hk_hooks) { | |||||
/* Skip any nonsession hook. */ | |||||
if (NG_HOOK_PRIVATE(hook) == NULL) | |||||
continue; | |||||
if (cookie.pointer == NG_HOOK_PRIVATE(hook)) | |||||
break; | |||||
} | |||||
CTR3(KTR_NET, "%20s: matched %p for %p", __func__, hook, cookie.pointer); | |||||
return (hook); | |||||
} | |||||
/************************************************************************** | /************************************************************************** | ||||
* Start of Netgraph entrypoints. * | * Start of Netgraph entrypoints. * | ||||
**************************************************************************/ | **************************************************************************/ | ||||
/* | /* | ||||
* Allocate the private data structure and link it with node. | * Allocate the private data structure and link it with node. | ||||
*/ | */ | ||||
static int | static int | ||||
▲ Show 20 Lines • Show All 123 Lines • ▼ Show 20 Lines | ng_pppoe_rcvmsg(node_p node, item_p item, hook_p lasthook) | ||||
/* Deal with message according to cookie and command. */ | /* Deal with message according to cookie and command. */ | ||||
switch (msg->header.typecookie) { | switch (msg->header.typecookie) { | ||||
case NGM_PPPOE_COOKIE: | case NGM_PPPOE_COOKIE: | ||||
switch (msg->header.cmd) { | switch (msg->header.cmd) { | ||||
case NGM_PPPOE_CONNECT: | case NGM_PPPOE_CONNECT: | ||||
case NGM_PPPOE_LISTEN: | case NGM_PPPOE_LISTEN: | ||||
case NGM_PPPOE_OFFER: | case NGM_PPPOE_OFFER: | ||||
case NGM_PPPOE_SERVICE: | case NGM_PPPOE_SERVICE: | ||||
case NGM_PPPOE_SEND_HURL: | |||||
case NGM_PPPOE_SEND_MOTM: | |||||
ourmsg = (struct ngpppoe_init_data *)msg->data; | ourmsg = (struct ngpppoe_init_data *)msg->data; | ||||
if (msg->header.arglen < sizeof(*ourmsg)) { | if (msg->header.arglen < sizeof(*ourmsg)) { | ||||
log(LOG_ERR, "ng_pppoe[%x]: init data too " | log(LOG_ERR, "ng_pppoe[%x]: init data too " | ||||
"small\n", node->nd_ID); | "small\n", node->nd_ID); | ||||
LEAVE(EMSGSIZE); | LEAVE(EMSGSIZE); | ||||
} | } | ||||
if (msg->header.cmd == NGM_PPPOE_SEND_HURL || | |||||
msg->header.cmd == NGM_PPPOE_SEND_MOTM) { | |||||
if (msg->header.arglen - sizeof(*ourmsg) > | if (msg->header.arglen - sizeof(*ourmsg) > | ||||
PPPOE_PADM_VALUE_SIZE) { | |||||
log(LOG_ERR, "ng_pppoe[%x]: message " | |||||
"too big\n", node->nd_ID); | |||||
LEAVE(EMSGSIZE); | |||||
} | |||||
} else { | |||||
if (msg->header.arglen - sizeof(*ourmsg) > | |||||
PPPOE_SERVICE_NAME_SIZE) { | PPPOE_SERVICE_NAME_SIZE) { | ||||
log(LOG_ERR, "ng_pppoe[%x]: service name " | log(LOG_ERR, "ng_pppoe[%x]: service name " | ||||
"too big\n", node->nd_ID); | "too big\n", node->nd_ID); | ||||
LEAVE(EMSGSIZE); | LEAVE(EMSGSIZE); | ||||
} | } | ||||
} | |||||
if (msg->header.arglen - sizeof(*ourmsg) < | if (msg->header.arglen - sizeof(*ourmsg) < | ||||
ourmsg->data_len) { | ourmsg->data_len) { | ||||
log(LOG_ERR, "ng_pppoe[%x]: init data has bad " | log(LOG_ERR, "ng_pppoe[%x]: init data has bad " | ||||
"length, %d should be %zd\n", node->nd_ID, | "length, %d should be %zd\n", node->nd_ID, | ||||
ourmsg->data_len, | ourmsg->data_len, | ||||
msg->header.arglen - sizeof (*ourmsg)); | msg->header.arglen - sizeof (*ourmsg)); | ||||
LEAVE(EMSGSIZE); | LEAVE(EMSGSIZE); | ||||
} | } | ||||
Show All 22 Lines | case NGM_PPPOE_SEND_MOTM: | ||||
/* | /* | ||||
* PPPOE_SERVICE advertisements are set up | * PPPOE_SERVICE advertisements are set up | ||||
* on sessions that are in PRIMED state. | * on sessions that are in PRIMED state. | ||||
*/ | */ | ||||
if (msg->header.cmd == NGM_PPPOE_SERVICE) | if (msg->header.cmd == NGM_PPPOE_SERVICE) | ||||
break; | break; | ||||
/* | |||||
* PADM messages are set up on active sessions. | |||||
*/ | |||||
if (msg->header.cmd == NGM_PPPOE_SEND_HURL || | |||||
msg->header.cmd == NGM_PPPOE_SEND_MOTM) { | |||||
if (sp->state != PPPOE_NEWCONNECTED && | |||||
sp->state != PPPOE_CONNECTED) { | |||||
log(LOG_NOTICE, "ng_pppoe[%x]: session is not " | |||||
"active\n", node->nd_ID); | |||||
LEAVE(EISCONN); | |||||
} | |||||
break; | |||||
} | |||||
if (sp->state != PPPOE_SNONE) { | if (sp->state != PPPOE_SNONE) { | ||||
log(LOG_NOTICE, "ng_pppoe[%x]: Session already " | log(LOG_NOTICE, "ng_pppoe[%x]: Session already " | ||||
"active\n", node->nd_ID); | "active\n", node->nd_ID); | ||||
LEAVE(EISCONN); | LEAVE(EISCONN); | ||||
} | } | ||||
/* | /* | ||||
* Set up prototype header. | * Set up prototype header. | ||||
Show All 38 Lines | case NGM_PPPOE_GET_STATUS: | ||||
break; | break; | ||||
} | } | ||||
case NGM_PPPOE_CONNECT: | case NGM_PPPOE_CONNECT: | ||||
{ | { | ||||
/* | /* | ||||
* Check the hook exists and is Uninitialised. | * Check the hook exists and is Uninitialised. | ||||
* Send a PADI request, and start the timeout logic. | * Send a PADI request, and start the timeout logic. | ||||
* Store the originator of this message so we can send | * Store the originator of this message so we can send | ||||
* a success of fail message to them later. | * a success or fail message to them later. | ||||
julian: can you fix the typo here while you are here.. of -> or | |||||
* Move the session to SINIT. | * Move the session to SINIT. | ||||
* Set up the session to the correct state and | * Set up the session to the correct state and | ||||
* start it. | * start it. | ||||
*/ | */ | ||||
int i, acnlen = 0, acnsep = 0, srvlen; | int acnpos, acnlen = 0, acnsep = 0; | ||||
int hupos, hulen = 0, husep = 0; | |||||
int i, srvpos, srvlen; | |||||
acnpos = 0; | |||||
for (i = 0; i < ourmsg->data_len; i++) { | for (i = 0; i < ourmsg->data_len; i++) { | ||||
if (ourmsg->data[i] == '\\') { | if (ourmsg->data[i] == '\\') { | ||||
acnlen = i; | acnlen = i; | ||||
acnsep = 1; | acnsep = 1; | ||||
break; | break; | ||||
} | } | ||||
} | } | ||||
srvlen = ourmsg->data_len - acnlen - acnsep; | hupos = acnlen + acnsep; | ||||
for (i = hupos; i < ourmsg->data_len; i++) { | |||||
if (ourmsg->data[i] == '|') { | |||||
hulen = i - hupos; | |||||
husep = 1; | |||||
break; | |||||
} | |||||
} | |||||
srvpos = hupos + hulen + husep; | |||||
srvlen = ourmsg->data_len - srvpos; | |||||
bcopy(ourmsg->data, neg->ac_name.data, acnlen); | bcopy(ourmsg->data + acnpos, neg->ac_name.data, acnlen); | ||||
neg->ac_name_len = acnlen; | neg->ac_name_len = acnlen; | ||||
neg->host_uniq.hdr.tag_type = PTT_HOST_UNIQ; | |||||
if (hulen == 0) { | |||||
/* Not provided, generate one */ | |||||
neg->host_uniq.hdr.tag_len = htons(sizeof(sp)); | |||||
bcopy(&sp, neg->host_uniq.data, sizeof(sp)); | |||||
neg->host_uniq_len = sizeof(sp); | |||||
} else if (hulen > 2 && ourmsg->data[hupos] == '0' && | |||||
ourmsg->data[hupos + 1] == 'x' && hulen % 2 == 0) { | |||||
/* Hex encoded */ | |||||
static const char hexdig[16] = "0123456789abcdef"; | |||||
int j; | |||||
neg->host_uniq.hdr.tag_len = htons((uint16_t)(hulen / 2 - 1)); | |||||
for (i = 0; i < hulen - 2; i++) { | |||||
for (j = 0; | |||||
j < 16 && | |||||
ourmsg->data[hupos + 2 + i] != hexdig[j]; | |||||
j++); | |||||
if (j == 16) | |||||
LEAVE(EINVAL); | |||||
if (i % 2 == 0) | |||||
neg->host_uniq.data[i / 2] = j << 4; | |||||
else | |||||
neg->host_uniq.data[i / 2] |= j; | |||||
} | |||||
neg->host_uniq_len = hulen / 2 - 1; | |||||
} else { | |||||
/* Plain string */ | |||||
neg->host_uniq.hdr.tag_len = htons((uint16_t)hulen); | |||||
bcopy(ourmsg->data + hupos, neg->host_uniq.data, hulen); | |||||
neg->host_uniq_len = hulen; | |||||
} | |||||
neg->service.hdr.tag_type = PTT_SRV_NAME; | neg->service.hdr.tag_type = PTT_SRV_NAME; | ||||
neg->service.hdr.tag_len = htons((uint16_t)srvlen); | neg->service.hdr.tag_len = htons((uint16_t)srvlen); | ||||
bcopy(ourmsg->data + acnlen + acnsep, | bcopy(ourmsg->data + srvpos, neg->service.data, srvlen); | ||||
neg->service.data, srvlen); | |||||
neg->service_len = srvlen; | neg->service_len = srvlen; | ||||
pppoe_start(sp); | pppoe_start(sp); | ||||
break; | break; | ||||
} | } | ||||
case NGM_PPPOE_LISTEN: | case NGM_PPPOE_LISTEN: | ||||
/* | /* | ||||
* Check the hook exists and is Uninitialised. | * Check the hook exists and is Uninitialised. | ||||
* Install the service matching string. | * Install the service matching string. | ||||
* Store the originator of this message so we can send | * Store the originator of this message so we can send | ||||
* a success of fail message to them later. | * a success or fail message to them later. | ||||
* Move the hook to 'LISTENING' | * Move the hook to 'LISTENING' | ||||
*/ | */ | ||||
neg->service.hdr.tag_type = PTT_SRV_NAME; | neg->service.hdr.tag_type = PTT_SRV_NAME; | ||||
neg->service.hdr.tag_len = | neg->service.hdr.tag_len = | ||||
htons((uint16_t)ourmsg->data_len); | htons((uint16_t)ourmsg->data_len); | ||||
if (ourmsg->data_len) | if (ourmsg->data_len) | ||||
bcopy(ourmsg->data, neg->service.data, | bcopy(ourmsg->data, neg->service.data, | ||||
ourmsg->data_len); | ourmsg->data_len); | ||||
neg->service_len = ourmsg->data_len; | neg->service_len = ourmsg->data_len; | ||||
neg->pkt->pkt_header.ph.code = PADT_CODE; | neg->pkt->pkt_header.ph.code = PADT_CODE; | ||||
/* | /* | ||||
* Wait for PADI packet coming from Ethernet. | * Wait for PADI packet coming from Ethernet. | ||||
*/ | */ | ||||
sp->state = PPPOE_LISTENING; | sp->state = PPPOE_LISTENING; | ||||
LIST_INSERT_HEAD(&privp->listeners, sp, sessions); | LIST_INSERT_HEAD(&privp->listeners, sp, sessions); | ||||
break; | break; | ||||
case NGM_PPPOE_OFFER: | case NGM_PPPOE_OFFER: | ||||
/* | /* | ||||
* Check the hook exists and is Uninitialised. | * Check the hook exists and is Uninitialised. | ||||
* Store the originator of this message so we can send | * Store the originator of this message so we can send | ||||
* a success of fail message to them later. | * a success of fail message to them later. | ||||
Done Inline Actionssame typo..guess I copied it julian: same typo..guess I copied it | |||||
* Store the AC-Name given and go to PRIMED. | * Store the AC-Name given and go to PRIMED. | ||||
*/ | */ | ||||
neg->ac_name.hdr.tag_type = PTT_AC_NAME; | neg->ac_name.hdr.tag_type = PTT_AC_NAME; | ||||
neg->ac_name.hdr.tag_len = | neg->ac_name.hdr.tag_len = | ||||
htons((uint16_t)ourmsg->data_len); | htons((uint16_t)ourmsg->data_len); | ||||
if (ourmsg->data_len) | if (ourmsg->data_len) | ||||
bcopy(ourmsg->data, neg->ac_name.data, | bcopy(ourmsg->data, neg->ac_name.data, | ||||
ourmsg->data_len); | ourmsg->data_len); | ||||
▲ Show 20 Lines • Show All 101 Lines • ▼ Show 20 Lines | case NGM_PPPOE_SETENADDR: | ||||
break; | break; | ||||
case NGM_PPPOE_SETMAXP: | case NGM_PPPOE_SETMAXP: | ||||
if (msg->header.arglen != sizeof(uint16_t)) | if (msg->header.arglen != sizeof(uint16_t)) | ||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
privp->max_payload.hdr.tag_type = PTT_MAX_PAYL; | privp->max_payload.hdr.tag_type = PTT_MAX_PAYL; | ||||
privp->max_payload.hdr.tag_len = htons(sizeof(uint16_t)); | privp->max_payload.hdr.tag_len = htons(sizeof(uint16_t)); | ||||
privp->max_payload.data = htons(*((uint16_t *)msg->data)); | privp->max_payload.data = htons(*((uint16_t *)msg->data)); | ||||
break; | break; | ||||
case NGM_PPPOE_SEND_HURL: | |||||
{ | |||||
struct mbuf *m; | |||||
/* Generate a packet of that type. */ | |||||
MGETHDR(m, M_NOWAIT, MT_DATA); | |||||
Done Inline ActionsThis is deprecated macro. Please use m_gethdr(M_NOWAIT, MT_DATA); glebius: This is deprecated macro. Please use m_gethdr(M_NOWAIT, MT_DATA); | |||||
if (m == NULL) | |||||
log(LOG_NOTICE, "ng_pppoe[%x]: session out of " | |||||
"mbufs\n", node->nd_ID); | |||||
else { | |||||
struct pppoe_full_hdr *wh; | |||||
struct pppoe_tag *tag; | |||||
int error = 0; | |||||
m->m_pkthdr.rcvif = NULL; | |||||
Done Inline ActionsThis is already done by the allocator. Not needed. glebius: This is already done by the allocator. Not needed. | |||||
m->m_pkthdr.len = m->m_len = sizeof(*wh); | |||||
Done Inline ActionsLooks like m_pkthdr.len is never read before it is overwritten later in L1167. glebius: Looks like m_pkthdr.len is never read before it is overwritten later in L1167. | |||||
wh = mtod(m, struct pppoe_full_hdr *); | |||||
bcopy(&sp->pkt_hdr, wh, sizeof(*wh)); | |||||
/* Revert the stored header to DISC/PADM mode. */ | |||||
wh->ph.code = PADM_CODE; | |||||
/* | |||||
* Configure ethertype depending on what | |||||
* was used during sessions stage. | |||||
*/ | |||||
if (wh->eh.ether_type == | |||||
ETHERTYPE_PPPOE_3COM_SESS) | |||||
wh->eh.ether_type = ETHERTYPE_PPPOE_3COM_DISC; | |||||
else | |||||
wh->eh.ether_type = ETHERTYPE_PPPOE_DISC; | |||||
/* | |||||
* Add PADM message and adjust sizes. | |||||
*/ | |||||
tag = (void *)(&wh->ph + 1); | |||||
tag->tag_type = PTT_HURL; | |||||
tag->tag_len = htons(ourmsg->data_len); | |||||
strncpy((char *)(tag + 1), ourmsg->data, ourmsg->data_len); | |||||
m->m_pkthdr.len = (m->m_len += sizeof(*tag) + | |||||
ourmsg->data_len); | |||||
wh->ph.length = htons(sizeof(*tag) + ourmsg->data_len); | |||||
NG_SEND_DATA_ONLY(error, | |||||
privp->ethernet_hook, m); | |||||
} | |||||
break; | |||||
} | |||||
case NGM_PPPOE_SEND_MOTM: | |||||
{ | |||||
struct mbuf *m; | |||||
/* Generate a packet of that type. */ | |||||
MGETHDR(m, M_NOWAIT, MT_DATA); | |||||
Done Inline ActionsSame comments on this block as on SEND_HURL. glebius: Same comments on this block as on SEND_HURL. | |||||
if (m == NULL) | |||||
log(LOG_NOTICE, "ng_pppoe[%x]: session out of " | |||||
"mbufs\n", node->nd_ID); | |||||
else { | |||||
struct pppoe_full_hdr *wh; | |||||
struct pppoe_tag *tag; | |||||
int error = 0; | |||||
m->m_pkthdr.rcvif = NULL; | |||||
m->m_pkthdr.len = m->m_len = sizeof(*wh); | |||||
wh = mtod(m, struct pppoe_full_hdr *); | |||||
bcopy(&sp->pkt_hdr, wh, sizeof(*wh)); | |||||
/* Revert the stored header to DISC/PADM mode. */ | |||||
wh->ph.code = PADM_CODE; | |||||
/* | |||||
* Configure ethertype depending on what | |||||
* was used during sessions stage. | |||||
*/ | |||||
if (wh->eh.ether_type == | |||||
ETHERTYPE_PPPOE_3COM_SESS) | |||||
wh->eh.ether_type = ETHERTYPE_PPPOE_3COM_DISC; | |||||
else | |||||
wh->eh.ether_type = ETHERTYPE_PPPOE_DISC; | |||||
/* | |||||
* Add PADM message and adjust sizes. | |||||
*/ | |||||
tag = (void *)(&wh->ph + 1); | |||||
tag->tag_type = PTT_MOTM; | |||||
tag->tag_len = htons(ourmsg->data_len); | |||||
strncpy((char *)(tag + 1), ourmsg->data, ourmsg->data_len); | |||||
m->m_pkthdr.len = (m->m_len += sizeof(*tag) + | |||||
ourmsg->data_len); | |||||
wh->ph.length = htons(sizeof(*tag) + ourmsg->data_len); | |||||
NG_SEND_DATA_ONLY(error, | |||||
privp->ethernet_hook, m); | |||||
} | |||||
break; | |||||
} | |||||
default: | default: | ||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
} | } | ||||
break; | break; | ||||
case NGM_ETHER_COOKIE: | case NGM_ETHER_COOKIE: | ||||
if (!(msg->header.flags & NGF_RESP)) | if (!(msg->header.flags & NGF_RESP)) | ||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
switch (msg->header.cmd) { | switch (msg->header.cmd) { | ||||
Show All 26 Lines | |||||
*/ | */ | ||||
static void | static void | ||||
pppoe_start(sessp sp) | pppoe_start(sessp sp) | ||||
{ | { | ||||
hook_p hook = sp->hook; | hook_p hook = sp->hook; | ||||
node_p node = NG_HOOK_NODE(hook); | node_p node = NG_HOOK_NODE(hook); | ||||
priv_p privp = NG_NODE_PRIVATE(node); | priv_p privp = NG_NODE_PRIVATE(node); | ||||
negp neg = sp->neg; | negp neg = sp->neg; | ||||
struct { | |||||
struct pppoe_tag hdr; | |||||
union uniq data; | |||||
} __packed uniqtag; | |||||
struct mbuf *m0; | struct mbuf *m0; | ||||
int error; | int error; | ||||
/* | /* | ||||
* Kick the state machine into starting up. | * Kick the state machine into starting up. | ||||
*/ | */ | ||||
CTR2(KTR_NET, "%20s: called %d", __func__, sp->Session_ID); | CTR2(KTR_NET, "%20s: called %d", __func__, sp->Session_ID); | ||||
sp->state = PPPOE_SINIT; | sp->state = PPPOE_SINIT; | ||||
/* | /* | ||||
* Reset the packet header to broadcast. Since we are | * Reset the packet header to broadcast. Since we are | ||||
* in a client mode use configured ethertype. | * in a client mode use configured ethertype. | ||||
*/ | */ | ||||
memcpy((void *)&neg->pkt->pkt_header.eh, &privp->eh, | memcpy((void *)&neg->pkt->pkt_header.eh, &privp->eh, | ||||
sizeof(struct ether_header)); | sizeof(struct ether_header)); | ||||
neg->pkt->pkt_header.ph.code = PADI_CODE; | neg->pkt->pkt_header.ph.code = PADI_CODE; | ||||
uniqtag.hdr.tag_type = PTT_HOST_UNIQ; | |||||
uniqtag.hdr.tag_len = htons((u_int16_t)sizeof(uniqtag.data)); | |||||
uniqtag.data.pointer = sp; | |||||
init_tags(sp); | init_tags(sp); | ||||
insert_tag(sp, &uniqtag.hdr); | insert_tag(sp, &neg->host_uniq.hdr); | ||||
insert_tag(sp, &neg->service.hdr); | insert_tag(sp, &neg->service.hdr); | ||||
if (privp->max_payload.data != 0) | if (privp->max_payload.data != 0) | ||||
insert_tag(sp, &privp->max_payload.hdr); | insert_tag(sp, &privp->max_payload.hdr); | ||||
make_packet(sp); | make_packet(sp); | ||||
/* | /* | ||||
* Send packet and prepare to retransmit it after timeout. | * Send packet and prepare to retransmit it after timeout. | ||||
*/ | */ | ||||
ng_callout(&neg->handle, node, hook, PPPOE_INITIAL_TIMEOUT * hz, | ng_callout(&neg->handle, node, hook, PPPOE_INITIAL_TIMEOUT * hz, | ||||
▲ Show 20 Lines • Show All 62 Lines • ▼ Show 20 Lines | send_maxp(sessp sp, const struct pppoe_tag *tag) | ||||
maxp = (struct ngpppoe_maxp *)msg->data; | maxp = (struct ngpppoe_maxp *)msg->data; | ||||
strncpy(maxp->hook, NG_HOOK_NAME(sp->hook), NG_HOOKSIZ); | strncpy(maxp->hook, NG_HOOK_NAME(sp->hook), NG_HOOKSIZ); | ||||
maxp->data = ntohs(((const struct maxptag *)tag)->data); | maxp->data = ntohs(((const struct maxptag *)tag)->data); | ||||
NG_SEND_MSG_ID(error, NG_HOOK_NODE(sp->hook), msg, sp->creator, 0); | NG_SEND_MSG_ID(error, NG_HOOK_NODE(sp->hook), msg, sp->creator, 0); | ||||
return (error); | return (error); | ||||
} | } | ||||
static int | |||||
send_hurl(sessp sp, const struct pppoe_tag *tag) | |||||
{ | |||||
int error, tlen; | |||||
struct ng_mesg *msg; | |||||
struct ngpppoe_padm *padm; | |||||
CTR2(KTR_NET, "%20s: called %d", __func__, sp->Session_ID); | |||||
NG_MKMESSAGE(msg, NGM_PPPOE_COOKIE, NGM_PPPOE_HURL, | |||||
sizeof(struct ngpppoe_padm), M_NOWAIT); | |||||
if (msg == NULL) | |||||
return (ENOMEM); | |||||
padm = (struct ngpppoe_padm *)msg->data; | |||||
tlen = min(PPPOE_PADM_VALUE_SIZE - 1, ntohs(tag->tag_len)); | |||||
strncpy(padm->msg, (const char *)(tag + 1), tlen); | |||||
padm->msg[tlen] = '\0'; | |||||
NG_SEND_MSG_ID(error, NG_HOOK_NODE(sp->hook), msg, sp->creator, 0); | |||||
return (error); | |||||
} | |||||
static int | |||||
send_motm(sessp sp, const struct pppoe_tag *tag) | |||||
{ | |||||
int error, tlen; | |||||
struct ng_mesg *msg; | |||||
struct ngpppoe_padm *padm; | |||||
CTR2(KTR_NET, "%20s: called %d", __func__, sp->Session_ID); | |||||
NG_MKMESSAGE(msg, NGM_PPPOE_COOKIE, NGM_PPPOE_MOTM, | |||||
sizeof(struct ngpppoe_padm), M_NOWAIT); | |||||
if (msg == NULL) | |||||
return (ENOMEM); | |||||
padm = (struct ngpppoe_padm *)msg->data; | |||||
tlen = min(PPPOE_PADM_VALUE_SIZE - 1, ntohs(tag->tag_len)); | |||||
strncpy(padm->msg, (const char *)(tag + 1), tlen); | |||||
padm->msg[tlen] = '\0'; | |||||
NG_SEND_MSG_ID(error, NG_HOOK_NODE(sp->hook), msg, sp->creator, 0); | |||||
return (error); | |||||
} | |||||
/* | /* | ||||
* Receive data from session hook and do something with it. | * Receive data from session hook and do something with it. | ||||
*/ | */ | ||||
static int | static int | ||||
ng_pppoe_rcvdata(hook_p hook, item_p item) | ng_pppoe_rcvdata(hook_p hook, item_p item) | ||||
{ | { | ||||
node_p node = NG_HOOK_NODE(hook); | node_p node = NG_HOOK_NODE(hook); | ||||
const priv_p privp = NG_NODE_PRIVATE(node); | const priv_p privp = NG_NODE_PRIVATE(node); | ||||
▲ Show 20 Lines • Show All 141 Lines • ▼ Show 20 Lines | |||||
*/ | */ | ||||
static int | static int | ||||
ng_pppoe_rcvdata_ether(hook_p hook, item_p item) | ng_pppoe_rcvdata_ether(hook_p hook, item_p item) | ||||
{ | { | ||||
node_p node = NG_HOOK_NODE(hook); | node_p node = NG_HOOK_NODE(hook); | ||||
const priv_p privp = NG_NODE_PRIVATE(node); | const priv_p privp = NG_NODE_PRIVATE(node); | ||||
sessp sp; | sessp sp; | ||||
const struct pppoe_tag *utag = NULL, *tag = NULL; | const struct pppoe_tag *utag = NULL, *tag = NULL; | ||||
const struct pppoe_tag sntag = { PTT_SRV_NAME, 0 }; | |||||
const struct pppoe_full_hdr *wh; | const struct pppoe_full_hdr *wh; | ||||
const struct pppoe_hdr *ph; | const struct pppoe_hdr *ph; | ||||
negp neg = NULL; | negp neg = NULL; | ||||
struct mbuf *m; | struct mbuf *m; | ||||
hook_p sendhook; | hook_p sendhook; | ||||
int error = 0; | int error = 0; | ||||
uint16_t session; | uint16_t session; | ||||
uint16_t length; | uint16_t length; | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | case PADI_CODE: | ||||
/* | /* | ||||
* We are a server: | * We are a server: | ||||
* Look for a hook with the required service and send | * Look for a hook with the required service and send | ||||
* the ENTIRE packet up there. It should come back to | * the ENTIRE packet up there. It should come back to | ||||
* a new hook in PRIMED state. Look there for further | * a new hook in PRIMED state. Look there for further | ||||
* processing. | * processing. | ||||
*/ | */ | ||||
tag = get_tag(ph, PTT_SRV_NAME); | tag = get_tag(ph, PTT_SRV_NAME); | ||||
if (tag == NULL) { | if (tag == NULL) | ||||
CTR1(KTR_NET, "%20s: PADI w/o Service-Name", | tag = &sntag; | ||||
__func__); | |||||
LEAVE(ENETUNREACH); | |||||
} | |||||
/* | /* | ||||
* First, try to match Service-Name against our | * First, try to match Service-Name against our | ||||
* listening hooks. If no success and we are in D-Link | * listening hooks. If no success and we are in D-Link | ||||
* compat mode and Service-Name is empty, then we | * compat mode and Service-Name is empty, then we | ||||
* broadcast the PADI to all listening hooks. | * broadcast the PADI to all listening hooks. | ||||
*/ | */ | ||||
sendhook = pppoe_match_svc(node, tag); | sendhook = pppoe_match_svc(node, tag); | ||||
if (sendhook != NULL) | if (sendhook != NULL) | ||||
NG_FWD_NEW_DATA(error, item, sendhook, m); | NG_FWD_NEW_DATA(error, item, sendhook, m); | ||||
else if (privp->flags & COMPAT_DLINK && | else if (privp->flags & COMPAT_DLINK && | ||||
ntohs(tag->tag_len) == 0) | ntohs(tag->tag_len) == 0) | ||||
error = pppoe_broadcast_padi(node, m); | error = pppoe_broadcast_padi(node, m); | ||||
else | else | ||||
error = ENETUNREACH; | error = ENETUNREACH; | ||||
break; | break; | ||||
case PADO_CODE: | case PADO_CODE: | ||||
/* | /* | ||||
* We are a client: | * We are a client: | ||||
* Use the host_uniq tag to find the hook this is in | * Use the host_uniq tag to find the hook this is in | ||||
* response to. Received #2, now send #3 | * response to. Received #2, now send #3 | ||||
* For now simply accept the first we receive. | * For now simply accept the first we receive. | ||||
*/ | */ | ||||
utag = get_tag(ph, PTT_HOST_UNIQ); | utag = get_tag(ph, PTT_HOST_UNIQ); | ||||
if ((utag == NULL) || | if (utag == NULL) { | ||||
(ntohs(utag->tag_len) != sizeof(sp))) { | |||||
log(LOG_NOTICE, "ng_pppoe[%x]: no host " | log(LOG_NOTICE, "ng_pppoe[%x]: no host " | ||||
"unique field\n", node->nd_ID); | "unique field\n", node->nd_ID); | ||||
LEAVE(ENETUNREACH); | LEAVE(ENETUNREACH); | ||||
} | } | ||||
sendhook = pppoe_finduniq(node, utag); | sendhook = pppoe_finduniq(node, utag); | ||||
if (sendhook == NULL) { | if (sendhook == NULL) { | ||||
log(LOG_NOTICE, "ng_pppoe[%x]: no " | log(LOG_NOTICE, "ng_pppoe[%x]: no " | ||||
▲ Show 20 Lines • Show All 73 Lines • ▼ Show 20 Lines | case PADR_CODE: | ||||
* hook this is in response to. | * hook this is in response to. | ||||
*/ | */ | ||||
utag = get_tag(ph, PTT_AC_COOKIE); | utag = get_tag(ph, PTT_AC_COOKIE); | ||||
if ((utag == NULL) || | if ((utag == NULL) || | ||||
(ntohs(utag->tag_len) != sizeof(sp))) { | (ntohs(utag->tag_len) != sizeof(sp))) { | ||||
LEAVE(ENETUNREACH); | LEAVE(ENETUNREACH); | ||||
} | } | ||||
sendhook = pppoe_finduniq(node, utag); | sendhook = pppoe_findcookie(node, utag); | ||||
if (sendhook == NULL) | if (sendhook == NULL) | ||||
LEAVE(ENETUNREACH); | LEAVE(ENETUNREACH); | ||||
/* | /* | ||||
* Check the session is in the right state. | * Check the session is in the right state. | ||||
* It needs to be in PPPOE_SOFFER or PPPOE_NEWCONNECTED. | * It needs to be in PPPOE_SOFFER or PPPOE_NEWCONNECTED. | ||||
* If the latter, then this is a retry by the client, | * If the latter, then this is a retry by the client, | ||||
* so be nice, and resend. | * so be nice, and resend. | ||||
▲ Show 20 Lines • Show All 59 Lines • ▼ Show 20 Lines | case PADS_CODE: | ||||
/* | /* | ||||
* We are a client: | * We are a client: | ||||
* Use the host_uniq tag to find the hook this is in | * Use the host_uniq tag to find the hook this is in | ||||
* response to. Take the session ID and store it away. | * response to. Take the session ID and store it away. | ||||
* Also make sure the pre-made header is correct and | * Also make sure the pre-made header is correct and | ||||
* set us into Session mode. | * set us into Session mode. | ||||
*/ | */ | ||||
utag = get_tag(ph, PTT_HOST_UNIQ); | utag = get_tag(ph, PTT_HOST_UNIQ); | ||||
if ((utag == NULL) || | if (utag == NULL) { | ||||
(ntohs(utag->tag_len) != sizeof(sp))) { | |||||
LEAVE (ENETUNREACH); | LEAVE (ENETUNREACH); | ||||
} | } | ||||
sendhook = pppoe_finduniq(node, utag); | sendhook = pppoe_finduniq(node, utag); | ||||
if (sendhook == NULL) | if (sendhook == NULL) | ||||
LEAVE(ENETUNREACH); | LEAVE(ENETUNREACH); | ||||
/* | /* | ||||
* Check the session is in the right state. | * Check the session is in the right state. | ||||
Show All 36 Lines | case PADT_CODE: | ||||
* Find matching peer/session combination. | * Find matching peer/session combination. | ||||
*/ | */ | ||||
sp = pppoe_findsession(privp, wh); | sp = pppoe_findsession(privp, wh); | ||||
if (sp == NULL) | if (sp == NULL) | ||||
LEAVE(ENETUNREACH); | LEAVE(ENETUNREACH); | ||||
/* Disconnect that hook. */ | /* Disconnect that hook. */ | ||||
ng_rmhook_self(sp->hook); | ng_rmhook_self(sp->hook); | ||||
break; | break; | ||||
case PADM_CODE: | |||||
/* | |||||
* We are a client: | |||||
* find matching peer/session combination. | |||||
*/ | |||||
sp = pppoe_findsession(privp, wh); | |||||
if (sp == NULL) | |||||
LEAVE (ENETUNREACH); | |||||
if ((tag = get_tag(ph, PTT_HURL))) | |||||
send_hurl(sp, tag); | |||||
if ((tag = get_tag(ph, PTT_MOTM))) | |||||
send_motm(sp, tag); | |||||
break; | |||||
default: | default: | ||||
LEAVE(EPFNOSUPPORT); | LEAVE(EPFNOSUPPORT); | ||||
} | } | ||||
break; | break; | ||||
case ETHERTYPE_PPPOE_3COM_SESS: | case ETHERTYPE_PPPOE_3COM_SESS: | ||||
case ETHERTYPE_PPPOE_SESS: | case ETHERTYPE_PPPOE_SESS: | ||||
/* | /* | ||||
* Find matching peer/session combination. | * Find matching peer/session combination. | ||||
▲ Show 20 Lines • Show All 258 Lines • ▼ Show 20 Lines | while((const char*)(pt + 1) <= end) { | ||||
case PTT_AC_NAME: | case PTT_AC_NAME: | ||||
case PTT_HOST_UNIQ: | case PTT_HOST_UNIQ: | ||||
case PTT_AC_COOKIE: | case PTT_AC_COOKIE: | ||||
case PTT_VENDOR: | case PTT_VENDOR: | ||||
case PTT_SRV_ERR: | case PTT_SRV_ERR: | ||||
case PTT_SYS_ERR: | case PTT_SYS_ERR: | ||||
case PTT_GEN_ERR: | case PTT_GEN_ERR: | ||||
case PTT_MAX_PAYL: | case PTT_MAX_PAYL: | ||||
case PTT_HURL: | |||||
case PTT_MOTM: | |||||
break; | break; | ||||
} | } | ||||
pt = (const struct pppoe_tag*)ptn; | pt = (const struct pppoe_tag*)ptn; | ||||
} | } | ||||
return NULL; | return NULL; | ||||
} | } | ||||
static int | static int | ||||
Show All 17 Lines |
can you fix the typo here while you are here.. of -> or