Changeset View
Changeset View
Standalone View
Standalone View
sys/netgraph/ng_pppoe.c
Show First 20 Lines • Show All 220 Lines • ▼ Show 20 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); | ||||
} | } | ||||
/************************************************************************** | /************************************************************************** | ||||
* Start of Netgraph entrypoints. * | * Start of Netgraph entrypoints. * | ||||
**************************************************************************/ | **************************************************************************/ | ||||
▲ Show 20 Lines • Show All 231 Lines • ▼ Show 20 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 of 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. | ||||
Show All 15 Lines | case NGM_PPPOE_LISTEN: | ||||
*/ | */ | ||||
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. | ||||
julianUnsubmitted 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 106 Lines • ▼ Show 20 Lines | case NGM_PPPOE_SETMAXP: | ||||
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; | ||||
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)) | ||||
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); | |||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
switch (msg->header.cmd) { | switch (msg->header.cmd) { | ||||
case NGM_ETHER_GET_ENADDR: | case NGM_ETHER_GET_ENADDR: | ||||
if (msg->header.arglen != ETHER_ADDR_LEN) | if (msg->header.arglen != ETHER_ADDR_LEN) | ||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
bcopy(msg->data, &privp->eh.ether_shost, | bcopy(msg->data, &privp->eh.ether_shost, | ||||
ETHER_ADDR_LEN); | ETHER_ADDR_LEN); | ||||
break; | break; | ||||
default: | default: | ||||
Done Inline ActionsThis is already done by the allocator. Not needed. glebius: This is already done by the allocator. Not needed. | |||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
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. | |||||
} | } | ||||
break; | break; | ||||
default: | default: | ||||
LEAVE(EINVAL); | LEAVE(EINVAL); | ||||
} | } | ||||
/* Take care of synchronous response, if any. */ | /* Take care of synchronous response, if any. */ | ||||
quit: | quit: | ||||
Show All 10 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; | ||||
/* | /* | ||||
Done Inline ActionsSame comments on this block as on SEND_HURL. glebius: Same comments on this block as on SEND_HURL. | |||||
* 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 337 Lines • ▼ Show 20 Lines | case ETHERTYPE_PPPOE_DISC: | ||||
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 149 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 20 Lines • Show All 343 Lines • Show Last 20 Lines |
can you fix the typo here while you are here.. of -> or