File: | src/usr.sbin/npppd/npppd/../pppoe/pppoe_session.c |
Warning: | line 111, column 6 Access to field 'state' results in a dereference of a null pointer (loaded from variable '_this') |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: pppoe_session.c,v 1.12 2021/03/29 03:54:40 yasuoka Exp $ */ | |||
2 | ||||
3 | /*- | |||
4 | * Copyright (c) 2009 Internet Initiative Japan Inc. | |||
5 | * All rights reserved. | |||
6 | * | |||
7 | * Redistribution and use in source and binary forms, with or without | |||
8 | * modification, are permitted provided that the following conditions | |||
9 | * are met: | |||
10 | * 1. Redistributions of source code must retain the above copyright | |||
11 | * notice, this list of conditions and the following disclaimer. | |||
12 | * 2. Redistributions in binary form must reproduce the above copyright | |||
13 | * notice, this list of conditions and the following disclaimer in the | |||
14 | * documentation and/or other materials provided with the distribution. | |||
15 | * | |||
16 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |||
17 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |||
18 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |||
19 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |||
20 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |||
21 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |||
22 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |||
23 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |||
24 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |||
25 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |||
26 | * SUCH DAMAGE. | |||
27 | */ | |||
28 | ||||
29 | /**@file | |||
30 | * Session management of PPPoE protocol | |||
31 | * $Id: pppoe_session.c,v 1.12 2021/03/29 03:54:40 yasuoka Exp $ | |||
32 | */ | |||
33 | ||||
34 | #include <sys/types.h> | |||
35 | #include <sys/socket.h> | |||
36 | #include <sys/uio.h> | |||
37 | #include <netinet/in.h> | |||
38 | #include <net/if.h> | |||
39 | #if defined(__NetBSD__) | |||
40 | #include <net/if_ether.h> | |||
41 | #else | |||
42 | #include <netinet/if_ether.h> | |||
43 | #endif | |||
44 | #include <net/if_dl.h> | |||
45 | #include <time.h> | |||
46 | #include <string.h> | |||
47 | #include <stdlib.h> | |||
48 | #include <stdio.h> | |||
49 | #include <event.h> | |||
50 | #include <syslog.h> | |||
51 | #include <stdarg.h> | |||
52 | ||||
53 | #include "hash.h" | |||
54 | #include "slist.h" | |||
55 | #include "debugutil.h" | |||
56 | #include "bytebuf.h" | |||
57 | #include "pppoe.h" | |||
58 | #include "pppoe_local.h" | |||
59 | ||||
60 | #include "npppd.h" | |||
61 | #include "ppp.h" | |||
62 | ||||
63 | #ifdef PPPOE_SESSION_DEBUG | |||
64 | #define PPPOE_SESSION_ASSERT(x) ASSERT(x)((void)0); | |||
65 | #define PPPOE_SESSION_DBG(x) pppoe_session_log x | |||
66 | #else | |||
67 | #define PPPOE_SESSION_ASSERT(x) | |||
68 | #define PPPOE_SESSION_DBG(x) | |||
69 | #endif | |||
70 | ||||
71 | #define pppoed_listener_this(sess)((pppoed_listener *)slist_get(&(sess)->pppoed->listener , (sess)->listener_index)) \ | |||
72 | ((pppoed_listener *)slist_get(&(sess)->pppoed->listener, \ | |||
73 | (sess)->listener_index)) | |||
74 | ||||
75 | static void pppoe_session_log (pppoe_session *, int, const char *, ...) __printflike(3,4)__attribute__((__format__ (__printf__, 3, 4))); | |||
76 | static int pppoe_session_send_PADS (pppoe_session *, struct pppoe_tlv *, | |||
77 | struct pppoe_tlv *); | |||
78 | static int pppoe_session_send_PADT (pppoe_session *); | |||
79 | static int pppoe_session_ppp_output (npppd_ppp *, u_char *, int, int); | |||
80 | static void pppoe_session_close_by_ppp(npppd_ppp *); | |||
81 | static int pppoe_session_bind_ppp (pppoe_session *); | |||
82 | static void pppoe_session_dispose_event(int, short, void *); | |||
83 | ||||
84 | /* Initialize PPPoE session context */ | |||
85 | int | |||
86 | pppoe_session_init(pppoe_session *_this, pppoed *_pppoed, int idx, | |||
87 | int session_id, u_char *ether_addr) | |||
88 | { | |||
89 | memset(_this, 0, sizeof(pppoe_session)); | |||
90 | ||||
91 | _this->pppoed = _pppoed; | |||
92 | _this->session_id = session_id; | |||
93 | _this->listener_index = idx; | |||
94 | memcpy(_this->ether_addr, ether_addr, ETHER_ADDR_LEN6); | |||
95 | ||||
96 | memcpy(_this->ehdr.ether_dhost, ether_addr, ETHER_ADDR_LEN6); | |||
97 | memcpy(_this->ehdr.ether_shost, pppoe_session_sock_ether_addr(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->ether_addr, | |||
98 | ETHER_ADDR_LEN6); | |||
99 | ||||
100 | evtimer_set(&_this->ev_disposing, pppoe_session_dispose_event, _this)event_set(&_this->ev_disposing, -1, 0, pppoe_session_dispose_event , _this); | |||
101 | ||||
102 | return 0; | |||
103 | } | |||
104 | ||||
105 | /* Disconnect PPPoE session */ | |||
106 | void | |||
107 | pppoe_session_disconnect(pppoe_session *_this) | |||
108 | { | |||
109 | struct timeval tv; | |||
110 | ||||
111 | if (_this->state != PPPOE_SESSION_STATE_DISPOSING2) { | |||
| ||||
112 | pppoe_session_send_PADT(_this); | |||
113 | ||||
114 | /* free process should be par event */ | |||
115 | timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0; | |||
116 | evtimer_add(&_this->ev_disposing, &tv)event_add(&_this->ev_disposing, &tv); | |||
117 | _this->state = PPPOE_SESSION_STATE_DISPOSING2; | |||
118 | } | |||
119 | if (_this->ppp != NULL((void *)0)) | |||
120 | ppp_phy_downed(_this->ppp); | |||
121 | } | |||
122 | ||||
123 | /* Stop PPPoE session */ | |||
124 | void | |||
125 | pppoe_session_stop(pppoe_session *_this) | |||
126 | { | |||
127 | if (_this->state != PPPOE_SESSION_STATE_DISPOSING2) | |||
128 | pppoe_session_disconnect(_this); | |||
129 | ||||
130 | } | |||
131 | ||||
132 | /* Finish PPPoE session */ | |||
133 | void | |||
134 | pppoe_session_fini(pppoe_session *_this) | |||
135 | { | |||
136 | evtimer_del(&_this->ev_disposing)event_del(&_this->ev_disposing); | |||
137 | } | |||
138 | ||||
139 | /* call back function from event(3) */ | |||
140 | static void | |||
141 | pppoe_session_dispose_event(int fd, short ev, void *ctx) | |||
142 | { | |||
143 | pppoe_session *_this; | |||
144 | ||||
145 | _this = ctx; | |||
146 | pppoed_pppoe_session_close_notify(_this->pppoed, _this); | |||
147 | } | |||
148 | ||||
149 | /* | |||
150 | * I/O | |||
151 | */ | |||
152 | void | |||
153 | pppoe_session_input(pppoe_session *_this, u_char *pkt, int lpkt) | |||
154 | { | |||
155 | int rval; | |||
156 | npppd_ppp *ppp; | |||
157 | ||||
158 | ppp = _this->ppp; | |||
159 | if (_this->ppp == NULL((void *)0)) | |||
160 | return; | |||
161 | ||||
162 | if (_this->state != PPPOE_SESSION_STATE_RUNNING1) | |||
163 | return; | |||
164 | ||||
165 | rval = ppp->recv_packet(ppp, pkt, lpkt, 0); | |||
166 | if (_this->ppp == NULL((void *)0)) /* ppp is freed */ | |||
167 | return; | |||
168 | ||||
169 | if (rval == 2) { | |||
170 | /* | |||
171 | * Quit this function before statistics counter | |||
172 | * is processed when the packet will be processed by | |||
173 | * PIPEX. Because current NPPPD PPPOE implementation | |||
174 | * is receiving all packet from BPF even though the | |||
175 | * PIPEX will process it. | |||
176 | */ | |||
177 | } else if (rval != 0) { | |||
178 | ppp->ierrors++; | |||
179 | } else { | |||
180 | ppp->ipackets++; | |||
181 | ppp->ibytes += lpkt; | |||
182 | } | |||
183 | ||||
184 | return; | |||
185 | } | |||
186 | ||||
187 | static int | |||
188 | pppoe_session_output(pppoe_session *_this, int is_disc, u_char *pkt, | |||
189 | int lpkt) | |||
190 | { | |||
191 | int sz, niov, tlen; | |||
192 | struct iovec iov[4]; | |||
193 | struct pppoe_header pppoe0, *pppoe; | |||
194 | char pad[ETHERMIN(64 - ((6 * 2) + 2) - 4)]; | |||
195 | ||||
196 | ||||
197 | niov = 0; | |||
198 | tlen = 0; | |||
199 | iov[niov].iov_base = &_this->ehdr; | |||
200 | iov[niov++].iov_len = sizeof(_this->ehdr); | |||
201 | ||||
202 | if (is_disc) { | |||
203 | _this->ehdr.ether_type = htons(ETHERTYPE_PPPOEDISC)(__uint16_t)(__builtin_constant_p(0x8863) ? (__uint16_t)(((__uint16_t )(0x8863) & 0xffU) << 8 | ((__uint16_t)(0x8863) & 0xff00U) >> 8) : __swap16md(0x8863)); | |||
204 | iov[niov].iov_base = pkt; | |||
205 | iov[niov++].iov_len = lpkt; | |||
206 | pppoe = (struct pppoe_header *)pkt; | |||
207 | pppoe->length = htons(lpkt - sizeof(pppoe0))(__uint16_t)(__builtin_constant_p(lpkt - sizeof(pppoe0)) ? (__uint16_t )(((__uint16_t)(lpkt - sizeof(pppoe0)) & 0xffU) << 8 | ((__uint16_t)(lpkt - sizeof(pppoe0)) & 0xff00U) >> 8) : __swap16md(lpkt - sizeof(pppoe0))); | |||
208 | tlen += lpkt; | |||
209 | } else { | |||
210 | _this->ehdr.ether_type = htons(ETHERTYPE_PPPOE)(__uint16_t)(__builtin_constant_p(0x8864) ? (__uint16_t)(((__uint16_t )(0x8864) & 0xffU) << 8 | ((__uint16_t)(0x8864) & 0xff00U) >> 8) : __swap16md(0x8864)); | |||
211 | pppoe0.ver = PPPOE_RFC2516_VER0x01; | |||
212 | pppoe0.type = PPPOE_RFC2516_TYPE0x01; | |||
213 | pppoe0.code = 0; | |||
214 | pppoe0.session_id = htons(_this->session_id)(__uint16_t)(__builtin_constant_p(_this->session_id) ? (__uint16_t )(((__uint16_t)(_this->session_id) & 0xffU) << 8 | ((__uint16_t)(_this->session_id) & 0xff00U) >> 8) : __swap16md(_this->session_id)); | |||
215 | pppoe0.length = htons(lpkt)(__uint16_t)(__builtin_constant_p(lpkt) ? (__uint16_t)(((__uint16_t )(lpkt) & 0xffU) << 8 | ((__uint16_t)(lpkt) & 0xff00U ) >> 8) : __swap16md(lpkt)); | |||
216 | iov[niov].iov_base = &pppoe0; | |||
217 | iov[niov++].iov_len = sizeof(pppoe0); | |||
218 | tlen += sizeof(pppoe0); | |||
219 | iov[niov].iov_base = pkt; | |||
220 | iov[niov++].iov_len = lpkt; | |||
221 | tlen += lpkt; | |||
222 | } | |||
223 | if (tlen < ETHERMIN(64 - ((6 * 2) + 2) - 4)) { | |||
224 | memset(pad, 0, ETHERMIN(64 - ((6 * 2) + 2) - 4) - tlen); | |||
225 | iov[niov].iov_base = pad; | |||
226 | iov[niov++].iov_len = ETHERMIN(64 - ((6 * 2) + 2) - 4) - tlen; | |||
227 | } | |||
228 | ||||
229 | sz = writev(pppoe_session_sock_bpf(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->bpf, iov, niov); | |||
230 | ||||
231 | return (sz > 0)? 0 : -1; | |||
232 | } | |||
233 | ||||
234 | static int | |||
235 | pppoe_session_send_PADT(pppoe_session *_this) | |||
236 | { | |||
237 | u_char bufspace[2048]; | |||
238 | bytebuffer *buf; | |||
239 | struct pppoe_header pppoe; | |||
240 | int rval = 0; | |||
241 | struct pppoe_tlv tlv; | |||
242 | ||||
243 | if ((buf = bytebuffer_wrap(bufspace, sizeof(bufspace))) == NULL((void *)0)) { | |||
244 | pppoe_session_log(_this, LOG_ERR3, | |||
245 | "bytebuffer_wrap() failed on %s(): %m", __func__); | |||
246 | return -1; | |||
247 | } | |||
248 | bytebuffer_clear(buf); | |||
249 | ||||
250 | /* | |||
251 | * PPPoE Header | |||
252 | */ | |||
253 | memset(&pppoe, 0, sizeof(pppoe)); | |||
254 | pppoe.ver = PPPOE_RFC2516_VER0x01; | |||
255 | pppoe.type = PPPOE_RFC2516_TYPE0x01; | |||
256 | pppoe.code = PPPOE_CODE_PADT0xa7; | |||
257 | pppoe.session_id = htons(_this->session_id)(__uint16_t)(__builtin_constant_p(_this->session_id) ? (__uint16_t )(((__uint16_t)(_this->session_id) & 0xffU) << 8 | ((__uint16_t)(_this->session_id) & 0xff00U) >> 8) : __swap16md(_this->session_id)); | |||
258 | bytebuffer_put(buf, &pppoe, sizeof(pppoe)); | |||
259 | ||||
260 | /* | |||
261 | * Tag - End-of-List | |||
262 | */ | |||
263 | tlv.type = htons(PPPOE_TAG_END_OF_LIST)(__uint16_t)(__builtin_constant_p(0x0000) ? (__uint16_t)(((__uint16_t )(0x0000) & 0xffU) << 8 | ((__uint16_t)(0x0000) & 0xff00U) >> 8) : __swap16md(0x0000)); | |||
264 | tlv.length = 0; | |||
265 | bytebuffer_put(buf, &tlv, sizeof(tlv)); | |||
266 | tlv.type = htons(PPPOE_TAG_END_OF_LIST)(__uint16_t)(__builtin_constant_p(0x0000) ? (__uint16_t)(((__uint16_t )(0x0000) & 0xffU) << 8 | ((__uint16_t)(0x0000) & 0xff00U) >> 8) : __swap16md(0x0000)); | |||
267 | tlv.length = 0; | |||
268 | bytebuffer_put(buf, &tlv, sizeof(tlv)); | |||
269 | ||||
270 | bytebuffer_flip(buf); | |||
271 | if (pppoe_session_output(_this, 1, bytebuffer_pointer(buf), | |||
272 | bytebuffer_remaining(buf)) != 0) { | |||
273 | pppoe_session_log(_this, LOG_ERR3, "pppoed_output failed: %m"); | |||
274 | rval = 1; | |||
275 | } | |||
276 | pppoe_session_log(_this, LOG_INFO6, "SendPADT"); | |||
277 | ||||
278 | bytebuffer_unwrap(buf); | |||
279 | bytebuffer_destroy(buf); | |||
280 | ||||
281 | return rval; | |||
282 | } | |||
283 | ||||
284 | /* send PADS */ | |||
285 | static int | |||
286 | pppoe_session_send_PADS(pppoe_session *_this, struct pppoe_tlv *hostuniq, | |||
287 | struct pppoe_tlv *service_name) | |||
288 | { | |||
289 | int rval, len; | |||
290 | u_char bufspace[2048], msgbuf[80]; | |||
291 | bytebuffer *buf; | |||
292 | struct pppoe_header pppoe; | |||
293 | struct pppoe_tlv tlv; | |||
294 | ||||
295 | if ((buf = bytebuffer_wrap(bufspace, sizeof(bufspace))) == NULL((void *)0)) { | |||
296 | pppoe_session_log(_this, LOG_ERR3, | |||
297 | "bytebuffer_wrap() failed on %s(): %m", __func__); | |||
298 | return -1; | |||
299 | } | |||
300 | bytebuffer_clear(buf); | |||
301 | ||||
302 | /* | |||
303 | * PPPoE Header | |||
304 | */ | |||
305 | memset(&pppoe, 0, sizeof(pppoe)); | |||
306 | pppoe.ver = PPPOE_RFC2516_VER0x01; | |||
307 | pppoe.type = PPPOE_RFC2516_TYPE0x01; | |||
308 | pppoe.code = PPPOE_CODE_PADS0x65; | |||
309 | pppoe.session_id = htons(_this->session_id)(__uint16_t)(__builtin_constant_p(_this->session_id) ? (__uint16_t )(((__uint16_t)(_this->session_id) & 0xffU) << 8 | ((__uint16_t)(_this->session_id) & 0xff00U) >> 8) : __swap16md(_this->session_id)); | |||
310 | bytebuffer_put(buf, &pppoe, sizeof(pppoe)); | |||
311 | ||||
312 | /* | |||
313 | * Tag - Service-Name | |||
314 | */ | |||
315 | msgbuf[0] = '\0'; | |||
316 | if (service_name != NULL((void *)0)) { | |||
317 | tlv.type = htons(PPPOE_TAG_SERVICE_NAME)(__uint16_t)(__builtin_constant_p(0x0101) ? (__uint16_t)(((__uint16_t )(0x0101) & 0xffU) << 8 | ((__uint16_t)(0x0101) & 0xff00U) >> 8) : __swap16md(0x0101)); | |||
318 | tlv.length = htons(service_name->length)(__uint16_t)(__builtin_constant_p(service_name->length) ? ( __uint16_t)(((__uint16_t)(service_name->length) & 0xffU ) << 8 | ((__uint16_t)(service_name->length) & 0xff00U ) >> 8) : __swap16md(service_name->length)); | |||
319 | bytebuffer_put(buf, &tlv, sizeof(tlv)); | |||
320 | ||||
321 | len = service_name->length; | |||
322 | if (len > 0) { | |||
323 | bytebuffer_put(buf, service_name->value, len); | |||
324 | strlcpy(msgbuf, service_name->value, | |||
325 | MINIMUM(len + 1, sizeof(msgbuf))(((len + 1) < (sizeof(msgbuf))) ? (len + 1) : (sizeof(msgbuf )))); | |||
326 | } | |||
327 | } | |||
328 | ||||
329 | /* | |||
330 | * Tag - Host-Uniq | |||
331 | */ | |||
332 | if (hostuniq != NULL((void *)0)) { | |||
333 | tlv.type = htons(PPPOE_TAG_HOST_UNIQ)(__uint16_t)(__builtin_constant_p(0x0103) ? (__uint16_t)(((__uint16_t )(0x0103) & 0xffU) << 8 | ((__uint16_t)(0x0103) & 0xff00U) >> 8) : __swap16md(0x0103)); | |||
334 | tlv.length = htons(hostuniq->length)(__uint16_t)(__builtin_constant_p(hostuniq->length) ? (__uint16_t )(((__uint16_t)(hostuniq->length) & 0xffU) << 8 | ((__uint16_t)(hostuniq->length) & 0xff00U) >> 8 ) : __swap16md(hostuniq->length)); | |||
335 | bytebuffer_put(buf, &tlv, sizeof(tlv)); | |||
336 | bytebuffer_put(buf, hostuniq->value, hostuniq->length); | |||
337 | } | |||
338 | tlv.type = htons(PPPOE_TAG_END_OF_LIST)(__uint16_t)(__builtin_constant_p(0x0000) ? (__uint16_t)(((__uint16_t )(0x0000) & 0xffU) << 8 | ((__uint16_t)(0x0000) & 0xff00U) >> 8) : __swap16md(0x0000)); | |||
339 | tlv.length = 0; | |||
340 | bytebuffer_put(buf, &tlv, sizeof(tlv)); | |||
341 | ||||
342 | bytebuffer_flip(buf); | |||
343 | rval = 0; | |||
344 | if (pppoe_session_output(_this, 1, bytebuffer_pointer(buf), | |||
345 | bytebuffer_remaining(buf)) != 0) { | |||
346 | pppoe_session_log(_this, LOG_ERR3, "pppoed_output failed: %m"); | |||
347 | rval = 1; | |||
348 | } | |||
349 | pppoe_session_log(_this, LOG_INFO6, "SendPADS serviceName=%s " | |||
350 | "hostUniq=%s", msgbuf, | |||
351 | hostuniq? pppoed_tlv_value_string(hostuniq) : "none"); | |||
352 | ||||
353 | bytebuffer_unwrap(buf); | |||
354 | bytebuffer_destroy(buf); | |||
355 | ||||
356 | return rval; | |||
357 | } | |||
358 | ||||
359 | /* process PADR from the peer */ | |||
360 | int | |||
361 | pppoe_session_recv_PADR(pppoe_session *_this, slist *tag_list) | |||
362 | { | |||
363 | pppoed *pppoed0 = _this->pppoed; | |||
364 | struct pppoe_tlv *tlv, *hostuniq, *service_name, *ac_cookie; | |||
365 | ||||
366 | service_name = NULL((void *)0); | |||
367 | hostuniq = NULL((void *)0); | |||
368 | ac_cookie = NULL((void *)0); | |||
369 | for (slist_itr_first(tag_list); slist_itr_has_next(tag_list); ) { | |||
370 | tlv = slist_itr_next(tag_list); | |||
371 | if (tlv->type == PPPOE_TAG_HOST_UNIQ0x0103) | |||
372 | hostuniq = tlv; | |||
373 | if (tlv->type == PPPOE_TAG_SERVICE_NAME0x0101) | |||
374 | service_name = tlv; | |||
375 | if (tlv->type == PPPOE_TAG_AC_COOKIE0x0104) | |||
376 | ac_cookie = tlv; | |||
377 | } | |||
378 | ||||
379 | if (ac_cookie) { | |||
380 | /* avoid a session which has already has cookie. */ | |||
381 | if (hash_lookup(pppoed0->acookie_hash, | |||
382 | (void *)ac_cookie->value) != NULL((void *)0)) | |||
383 | goto fail; | |||
384 | ||||
385 | _this->acookie = *(uint32_t *)(ac_cookie->value); | |||
386 | hash_insert(pppoed0->acookie_hash, | |||
387 | (void *)(intptr_t)_this->acookie, _this); | |||
388 | } | |||
389 | ||||
390 | if (pppoe_session_send_PADS(_this, hostuniq, service_name) != 0) | |||
391 | goto fail; | |||
392 | ||||
393 | if (pppoe_session_bind_ppp(_this) != 0) | |||
394 | goto fail; | |||
395 | ||||
396 | _this->state = PPPOE_SESSION_STATE_RUNNING1; | |||
397 | return 0; | |||
398 | fail: | |||
399 | return -1; | |||
400 | } | |||
401 | ||||
402 | /* process PADT from the peer */ | |||
403 | int | |||
404 | pppoe_session_recv_PADT(pppoe_session *_this, slist *tag_list) | |||
405 | { | |||
406 | pppoe_session_log(_this, LOG_INFO6, "RecvPADT"); | |||
407 | ||||
408 | pppoe_session_stop(_this); | |||
409 | _this->state = PPPOE_SESSION_STATE_DISPOSING2; | |||
410 | ||||
411 | return 0; | |||
412 | } | |||
413 | ||||
414 | /* | |||
415 | * Log | |||
416 | */ | |||
417 | static void | |||
418 | pppoe_session_log(pppoe_session *_this, int prio, const char *fmt, ...) | |||
419 | { | |||
420 | char logbuf[BUFSIZ1024]; | |||
421 | va_list ap; | |||
422 | ||||
423 | PPPOE_SESSION_ASSERT(_this != NULL); | |||
424 | va_start(ap, fmt)__builtin_va_start(ap, fmt); | |||
425 | #ifdef PPPOED_MULTIPLE | |||
426 | snprintf(logbuf, sizeof(logbuf), "pppoed id=%u session=%d %s", | |||
427 | _this->pppoed->id, _this->session_id, fmt); | |||
428 | #else | |||
429 | snprintf(logbuf, sizeof(logbuf), "pppoed if=%s session=%d %s", | |||
430 | pppoe_session_listen_ifname(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->listen_ifname, _this->session_id, fmt); | |||
431 | #endif | |||
432 | vlog_printf(prio, logbuf, ap); | |||
433 | va_end(ap)__builtin_va_end(ap); | |||
434 | } | |||
435 | ||||
436 | /* | |||
437 | * PPP | |||
438 | */ | |||
439 | static int | |||
440 | pppoe_session_ppp_output(npppd_ppp *ppp, u_char *pkt, int lpkt, int flag) | |||
441 | { | |||
442 | int rval; | |||
443 | pppoe_session *_this; | |||
444 | ||||
445 | _this = ppp->phy_context; | |||
446 | ||||
447 | rval = pppoe_session_output(_this, 0, pkt, lpkt); | |||
448 | ||||
449 | if (_this->ppp == NULL((void *)0)) /* ppp is freed */ | |||
450 | return 0; | |||
451 | ||||
452 | if (rval != 0) { | |||
453 | ppp->oerrors++; | |||
454 | } else { | |||
455 | ppp->opackets++; | |||
456 | ppp->obytes += lpkt; | |||
457 | } | |||
458 | ||||
459 | return 0; | |||
460 | } | |||
461 | ||||
462 | static void | |||
463 | pppoe_session_close_by_ppp(npppd_ppp *ppp) | |||
464 | { | |||
465 | pppoe_session *_this; | |||
466 | ||||
467 | _this = ppp->phy_context; | |||
| ||||
468 | PPPOE_SESSION_ASSERT(_this != NULL); | |||
469 | if (_this != NULL((void *)0)) | |||
470 | /* do this before pptp_call_disconnect() */ | |||
471 | _this->ppp = NULL((void *)0); | |||
472 | ||||
473 | pppoe_session_disconnect(_this); | |||
474 | } | |||
475 | ||||
476 | /* bind for PPP */ | |||
477 | static int | |||
478 | pppoe_session_bind_ppp(pppoe_session *_this) | |||
479 | { | |||
480 | int len; | |||
481 | npppd_ppp *ppp; | |||
482 | struct sockaddr_dl sdl; | |||
483 | ||||
484 | ppp = NULL((void *)0); | |||
485 | if ((ppp = ppp_create()) == NULL((void *)0)) | |||
486 | goto fail; | |||
487 | ||||
488 | PPPOE_SESSION_ASSERT(_this->ppp == NULL); | |||
489 | ||||
490 | if (_this->ppp != NULL((void *)0)) | |||
491 | return -1; | |||
492 | ||||
493 | _this->ppp = ppp; | |||
494 | ||||
495 | ppp->tunnel_type = NPPPD_TUNNEL_PPPOE3; | |||
496 | ppp->tunnel_session_id = _this->session_id; | |||
497 | ppp->phy_context = _this; | |||
498 | ppp->send_packet = pppoe_session_ppp_output; | |||
499 | ppp->phy_close = pppoe_session_close_by_ppp; | |||
500 | ||||
501 | strlcpy(ppp->phy_label, PPPOE_SESSION_LISTENER_TUN_NAME(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->tun_name, | |||
502 | sizeof(ppp->phy_label)); | |||
503 | ||||
504 | memset(&sdl, 0, sizeof(sdl)); | |||
505 | sdl.sdl_len = sizeof(sdl); | |||
506 | sdl.sdl_family = AF_LINK18; | |||
507 | sdl.sdl_index = if_nametoindex(pppoe_session_listen_ifname(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->listen_ifname); | |||
508 | len = strlen(pppoe_session_listen_ifname(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->listen_ifname); | |||
509 | memcpy(sdl.sdl_data, pppoe_session_listen_ifname(_this)((pppoed_listener *)slist_get(&(_this)->pppoed->listener , (_this)->listener_index))->listen_ifname, len); | |||
510 | sdl.sdl_nlen = len; | |||
511 | sdl.sdl_alen = ETHER_ADDR_LEN6; | |||
512 | memcpy(sdl.sdl_data + len, _this->ether_addr, ETHER_ADDR_LEN6); | |||
513 | ||||
514 | memcpy(&ppp->phy_info.peer_dl, &sdl, sizeof(sdl)); | |||
515 | ||||
516 | if (ppp_init(npppd_get_npppd(), ppp) != 0) | |||
517 | goto fail; | |||
518 | ppp->has_acf = 0; | |||
519 | ||||
520 | ||||
521 | pppoe_session_log(_this, LOG_NOTICE5, "logtype=PPPBind ppp=%d", ppp->id); | |||
522 | ppp_start(ppp); | |||
523 | ||||
524 | return 0; | |||
525 | fail: | |||
526 | pppoe_session_log(_this, LOG_ERR3, "failed binding ppp"); | |||
527 | ||||
528 | if (ppp != NULL((void *)0)) | |||
529 | ppp_destroy(ppp); | |||
530 | _this->ppp = NULL((void *)0); | |||
531 | ||||
532 | return 1; | |||
533 | } |