]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-network/sd-pppoe.c
util-lib: split our string related calls from util.[ch] into its own file string...
[thirdparty/systemd.git] / src / libsystemd-network / sd-pppoe.c
CommitLineData
cda391c3
TG
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright (C) 2014 Tom Gundersen
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22/* See RFC 2516 */
23
cda391c3
TG
24#include <net/if.h>
25#include <netinet/in.h>
07630cea 26#include <sys/ioctl.h>
cda391c3 27#include <linux/if_pppox.h>
07630cea
LP
28#include <linux/ppp-ioctl.h>
29#include <linux/ppp_defs.h>
cda391c3
TG
30
31#include "sd-pppoe.h"
32
07630cea 33#include "async.h"
cda391c3 34#include "event-util.h"
3df3e884 35#include "random-util.h"
cda391c3 36#include "socket-util.h"
07630cea 37#include "string-util.h"
cda391c3 38#include "utf8.h"
07630cea 39#include "util.h"
cda391c3
TG
40
41#define PPPOE_MAX_PACKET_SIZE 1484
42#define PPPOE_MAX_PADR_RESEND 16
43
44/* TODO: move this to socket-util.h without getting into
45 * a mess with the includes */
46union sockaddr_union_pppox {
47 struct sockaddr sa;
48 struct sockaddr_pppox pppox;
49};
50
51typedef enum PPPoEState {
52 PPPOE_STATE_INITIALIZING,
53 PPPOE_STATE_REQUESTING,
54 PPPOE_STATE_RUNNING,
55 PPPOE_STATE_STOPPED,
56 _PPPOE_STATE_MAX,
57 _PPPOE_STATE_INVALID = -1,
58} PPPoEState;
59
60typedef struct PPPoETags {
61 char *service_name;
62 char *ac_name;
63 uint8_t *host_uniq;
64 size_t host_uniq_len;
65 uint8_t *cookie;
66 size_t cookie_len;
67} PPPoETags;
68
69struct sd_pppoe {
9c8e3101 70 unsigned n_ref;
cda391c3
TG
71
72 PPPoEState state;
73 uint64_t host_uniq;
74
75 int ifindex;
76 char *ifname;
77
78 sd_event *event;
79 int event_priority;
80 int fd;
81 sd_event_source *io;
82 sd_event_source *timeout;
83 int padr_resend_count;
84
85 char *service_name;
86 struct ether_addr peer_mac;
87 be16_t session_id;
88
89 int pppoe_fd;
90 int channel;
91
92 sd_pppoe_cb_t cb;
93 void *userdata;
94
95 PPPoETags tags;
96};
97
98#define PPPOE_PACKET_LENGTH(header) \
99 be16toh((header)->length)
100
101#define PPPOE_PACKET_TAIL(packet) \
c962cb68 102 (struct pppoe_tag*)((uint8_t*)(packet) + sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet))
cda391c3 103
c962cb68
TG
104#define PPPOE_TAG_LENGTH(tag) \
105 be16toh((tag)->tag_len)
cda391c3 106
c962cb68
TG
107#define PPPOE_TAG_TYPE(tag) \
108 (tag)->tag_type
cda391c3
TG
109
110#define PPPOE_TAG_NEXT(tag) \
111 (struct pppoe_tag *)((uint8_t *)(tag) + sizeof(struct pppoe_tag) + PPPOE_TAG_LENGTH(tag))
112
113#define PPPOE_TAGS_FOREACH(tag, header) \
114 for (tag = (header)->tag; \
115 ((uint8_t *)(tag) + sizeof(struct pppoe_tag) < (uint8_t*)PPPOE_PACKET_TAIL(header)) && \
116 (PPPOE_TAG_NEXT(tag) <= PPPOE_PACKET_TAIL(header)) && \
117 (tag >= (header)->tag) && \
118 (PPPOE_TAG_TYPE(tag) != PTT_EOL); \
119 tag = PPPOE_TAG_NEXT(tag))
120
121static void pppoe_tags_clear(PPPoETags *tags) {
122 free(tags->service_name);
123 free(tags->ac_name);
124 free(tags->host_uniq);
125 free(tags->cookie);
126
127 zero(*tags);
128}
129
130int sd_pppoe_set_ifindex(sd_pppoe *ppp, int ifindex) {
131 assert_return(ppp, -EINVAL);
132 assert_return(ifindex > 0, -EINVAL);
133
134 ppp->ifindex = ifindex;
135
136 return 0;
137}
138
139int sd_pppoe_set_ifname(sd_pppoe *ppp, const char *ifname) {
140 char *name;
141
142 assert_return(ppp, -EINVAL);
143 assert_return(ifname, -EINVAL);
144
145 if (strlen(ifname) > IFNAMSIZ)
146 return -EINVAL;
147
148 name = strdup(ifname);
149 if (!name)
150 return -ENOMEM;
151
152 free(ppp->ifname);
153 ppp->ifname = name;
154
155 return 0;
156}
157
158int sd_pppoe_set_service_name(sd_pppoe *ppp, const char *service_name) {
159 _cleanup_free_ char *name = NULL;
160
161 assert_return(ppp, -EINVAL);
162
163 if (service_name) {
164 name = strdup(service_name);
165 if (!name)
166 return -ENOMEM;
167 }
168
169 free(ppp->service_name);
170 ppp->service_name = name;
171 name = NULL;
172
173 return 0;
174}
175
176int sd_pppoe_attach_event(sd_pppoe *ppp, sd_event *event, int priority) {
177 int r;
178
179 assert_return(ppp, -EINVAL);
180 assert_return(!ppp->event, -EBUSY);
181
182 if (event)
183 ppp->event = sd_event_ref(event);
184 else {
185 r = sd_event_default(&ppp->event);
186 if (r < 0)
187 return r;
188 }
189
190 ppp->event_priority = priority;
191
192 return 0;
193}
194
195int sd_pppoe_detach_event(sd_pppoe *ppp) {
196 assert_return(ppp, -EINVAL);
197
198 ppp->event = sd_event_unref(ppp->event);
199
200 return 0;
201}
202
203sd_pppoe *sd_pppoe_ref(sd_pppoe *ppp) {
9c8e3101
LP
204
205 if (!ppp)
206 return NULL;
207
208 assert(ppp->n_ref > 0);
209 ppp->n_ref++;
cda391c3
TG
210
211 return ppp;
212}
213
214sd_pppoe *sd_pppoe_unref(sd_pppoe *ppp) {
cda391c3 215
9c8e3101
LP
216 if (!ppp)
217 return NULL;
218
219 assert(ppp->n_ref > 0);
220 ppp->n_ref--;
221
222 if (ppp->n_ref > 0)
223 return NULL;
224
225 pppoe_tags_clear(&ppp->tags);
226 free(ppp->ifname);
227 free(ppp->service_name);
228 sd_pppoe_stop(ppp);
229 sd_pppoe_detach_event(ppp);
230
231 free(ppp);
cda391c3
TG
232 return NULL;
233}
234
235int sd_pppoe_new (sd_pppoe **ret) {
236 sd_pppoe *ppp;
237
238 assert_return(ret, -EINVAL);
239
240 ppp = new0(sd_pppoe, 1);
241 if (!ppp)
242 return -ENOMEM;
243
9c8e3101 244 ppp->n_ref = 1;
cda391c3
TG
245 ppp->state = _PPPOE_STATE_INVALID;
246 ppp->ifindex = -1;
247 ppp->fd = -1;
248 ppp->pppoe_fd = -1;
249 ppp->padr_resend_count = PPPOE_MAX_PADR_RESEND;
250
251 *ret = ppp;
252
253 return 0;
254}
255
256int sd_pppoe_get_channel(sd_pppoe *ppp, int *channel) {
257 assert_return(ppp, -EINVAL);
258 assert_return(channel, -EINVAL);
259 assert_return(ppp->pppoe_fd != -1, -EUNATCH);
260 assert_return(ppp->state == PPPOE_STATE_RUNNING, -EUNATCH);
261
262 *channel = ppp->channel;
263
264 return 0;
265}
266
267int sd_pppoe_set_callback(sd_pppoe *ppp, sd_pppoe_cb_t cb, void *userdata) {
268 assert_return(ppp, -EINVAL);
269
270 ppp->cb = cb;
271 ppp->userdata = userdata;
272
273 return 0;
274}
275
276static void pppoe_tag_append(struct pppoe_hdr *packet, size_t packet_size, be16_t tag_type, const void *tag_data, uint16_t tag_len) {
277 struct pppoe_tag *tag;
278
279 assert(packet);
280 assert(sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet) + sizeof(struct pppoe_tag) + tag_len <= packet_size);
281 assert(!(!tag_data ^ !tag_len));
282
283 tag = PPPOE_PACKET_TAIL(packet);
284
c962cb68
TG
285 tag->tag_len = htobe16(tag_len);
286 tag->tag_type = tag_type;
cda391c3
TG
287 if (tag_data)
288 memcpy(tag->tag_data, tag_data, tag_len);
289
290 packet->length = htobe16(PPPOE_PACKET_LENGTH(packet) + sizeof(struct pppoe_tag) + tag_len);
291}
292
293static int pppoe_send(sd_pppoe *ppp, uint8_t code) {
294 union sockaddr_union link = {
295 .ll = {
296 .sll_family = AF_PACKET,
297 .sll_protocol = htons(ETH_P_PPP_DISC),
298 .sll_halen = ETH_ALEN,
299 },
300 };
301 _cleanup_free_ struct pppoe_hdr *packet = NULL;
302 int r;
303
304 assert(ppp);
305 assert(ppp->fd != -1);
306 assert(IN_SET(code, PADI_CODE, PADR_CODE, PADT_CODE));
307
308 link.ll.sll_ifindex = ppp->ifindex;
309 if (code == PADI_CODE)
310 memset(&link.ll.sll_addr, 0xff, ETH_ALEN);
311 else
312 memcpy(&link.ll.sll_addr, &ppp->peer_mac, ETH_ALEN);
313
314 packet = malloc0(PPPOE_MAX_PACKET_SIZE);
315 if (!packet)
316 return -ENOMEM;
317
318 packet->ver = 0x1;
319 packet->type = 0x1;
320 packet->code = code;
321 if (code == PADT_CODE)
322 packet->sid = ppp->session_id;
323
324 /* Service-Name */
325 pppoe_tag_append(packet, PPPOE_MAX_PACKET_SIZE, PTT_SRV_NAME,
326 ppp->service_name, ppp->service_name ? strlen(ppp->service_name) : 0);
327
328 /* AC-Cookie */
329 if (code == PADR_CODE && ppp->tags.cookie)
330 pppoe_tag_append(packet, PPPOE_MAX_PACKET_SIZE, PTT_AC_COOKIE,
331 ppp->tags.cookie, ppp->tags.cookie_len);
332
333 /* Host-Uniq */
334 if (code != PADT_CODE) {
335 ppp->host_uniq = random_u64();
336
337 pppoe_tag_append(packet, PPPOE_MAX_PACKET_SIZE, PTT_HOST_UNIQ,
338 &ppp->host_uniq, sizeof(ppp->host_uniq));
339 }
340
341 r = sendto(ppp->fd, packet, sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet),
342 0, &link.sa, sizeof(link.ll));
343 if (r < 0)
344 return -errno;
345
346 return 0;
347}
348
349static int pppoe_timeout(sd_event_source *s, uint64_t usec, void *userdata);
350
351static int pppoe_arm_timeout(sd_pppoe *ppp) {
352 _cleanup_event_source_unref_ sd_event_source *timeout = NULL;
a7f7d1bd 353 usec_t next_timeout = 0;
cda391c3
TG
354 int r;
355
356 assert(ppp);
357
358 r = sd_event_now(ppp->event, clock_boottime_or_monotonic(), &next_timeout);
38a03f06 359 if (r < 0)
cda391c3
TG
360 return r;
361
362 next_timeout += 500 * USEC_PER_MSEC;
363
364 r = sd_event_add_time(ppp->event, &timeout, clock_boottime_or_monotonic(), next_timeout,
365 10 * USEC_PER_MSEC, pppoe_timeout, ppp);
366 if (r < 0)
367 return r;
368
369 r = sd_event_source_set_priority(timeout, ppp->event_priority);
370 if (r < 0)
371 return r;
372
373 sd_event_source_unref(ppp->timeout);
374 ppp->timeout = timeout;
375 timeout = NULL;
376
377 return 0;
378}
379
380static int pppoe_send_initiation(sd_pppoe *ppp) {
381 int r;
382
383 r = pppoe_send(ppp, PADI_CODE);
384 if (r < 0)
385 return r;
386
387 log_debug("PPPoE: sent DISCOVER (Service-Name: %s)",
8b66ad17 388 strna(ppp->service_name));
cda391c3
TG
389
390 pppoe_arm_timeout(ppp);
391
392 return r;
393}
394
395static int pppoe_send_request(sd_pppoe *ppp) {
396 int r;
397
398 r = pppoe_send(ppp, PADR_CODE);
399 if (r < 0)
400 return r;
401
402 log_debug("PPPoE: sent REQUEST");
403
404 ppp->padr_resend_count --;
405
406 pppoe_arm_timeout(ppp);
407
408 return 0;
409}
410
411static int pppoe_send_terminate(sd_pppoe *ppp) {
412 int r;
413
414 r = pppoe_send(ppp, PADT_CODE);
415 if (r < 0)
416 return r;
417
418 log_debug("PPPoE: sent TERMINATE");
419
420 return 0;
421}
422
423static int pppoe_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
424 sd_pppoe *ppp = userdata;
425 int r;
426
427 assert(ppp);
428
429 switch (ppp->state) {
430 case PPPOE_STATE_INITIALIZING:
431 r = pppoe_send_initiation(ppp);
432 if (r < 0)
da927ba9 433 log_warning_errno(r, "PPPoE: sending PADI failed: %m");
cda391c3
TG
434
435 break;
436 case PPPOE_STATE_REQUESTING:
437 if (ppp->padr_resend_count <= 0) {
438 log_debug("PPPoE: PADR timed out, restarting PADI");
439
440 r = pppoe_send_initiation(ppp);
441 if (r < 0)
da927ba9 442 log_warning_errno(r, "PPPoE: sending PADI failed: %m");
cda391c3
TG
443
444 ppp->padr_resend_count = PPPOE_MAX_PADR_RESEND;
445 ppp->state = PPPOE_STATE_INITIALIZING;
446 } else {
447 r = pppoe_send_request(ppp);
448 if (r < 0)
da927ba9 449 log_warning_errno(r, "PPPoE: sending PADR failed: %m");
cda391c3
TG
450 }
451
452 break;
453 default:
454 assert_not_reached("timeout in invalid state");
455 }
456
457 return 0;
458}
459
460static int pppoe_tag_parse_binary(struct pppoe_tag *tag, uint8_t **ret, size_t *length) {
461 uint8_t *data;
462
463 assert(ret);
464 assert(length);
465
466 data = memdup(tag->tag_data, PPPOE_TAG_LENGTH(tag));
467 if (!data)
468 return -ENOMEM;
469
470 free(*ret);
471 *ret = data;
472 *length = PPPOE_TAG_LENGTH(tag);
473
474 return 0;
475}
476
477static int pppoe_tag_parse_string(struct pppoe_tag *tag, char **ret) {
478 char *string;
479
480 assert(ret);
481
482 string = strndup(tag->tag_data, PPPOE_TAG_LENGTH(tag));
483 if (!string)
484 return -ENOMEM;
485
486 free(*ret);
487 *ret = string;
488
489 return 0;
490}
491
492static int pppoe_payload_parse(PPPoETags *tags, struct pppoe_hdr *header) {
493 struct pppoe_tag *tag;
494 int r;
495
496 assert(tags);
497
498 pppoe_tags_clear(tags);
499
500 PPPOE_TAGS_FOREACH(tag, header) {
501 switch (PPPOE_TAG_TYPE(tag)) {
502 case PTT_SRV_NAME:
503 r = pppoe_tag_parse_string(tag, &tags->service_name);
504 if (r < 0)
505 return r;
506
507 break;
508 case PTT_AC_NAME:
509 r = pppoe_tag_parse_string(tag, &tags->ac_name);
510 if (r < 0)
511 return r;
512
513 break;
514 case PTT_HOST_UNIQ:
515 r = pppoe_tag_parse_binary(tag, &tags->host_uniq, &tags->host_uniq_len);
516 if (r < 0)
517 return r;
518
519 break;
520 case PTT_AC_COOKIE:
521 r = pppoe_tag_parse_binary(tag, &tags->cookie, &tags->cookie_len);
522 if (r < 0)
523 return r;
524
525 break;
526 case PTT_SRV_ERR:
527 case PTT_SYS_ERR:
528 case PTT_GEN_ERR:
529 {
530 _cleanup_free_ char *error = NULL;
531
532 /* TODO: do something more sensible with the error messages */
533 r = pppoe_tag_parse_string(tag, &error);
534 if (r < 0)
535 return r;
536
537 if (strlen(error) > 0 && utf8_is_valid(error))
538 log_debug("PPPoE: error - '%s'", error);
539 else
540 log_debug("PPPoE: error");
541
542 break;
543 }
544 default:
545 log_debug("PPPoE: ignoring unknown PPPoE tag type: 0x%.2x", PPPOE_TAG_TYPE(tag));
546 }
547 }
548
549 return 0;
550}
551
552static int pppoe_open_pppoe_socket(sd_pppoe *ppp) {
553 int s;
554
555 assert(ppp);
556 assert(ppp->pppoe_fd == -1);
557
558 s = socket(AF_PPPOX, SOCK_STREAM, 0);
559 if (s < 0)
560 return -errno;
561
562 ppp->pppoe_fd = s;
563
564 return 0;
565}
566
567static int pppoe_connect_pppoe_socket(sd_pppoe *ppp) {
568 union sockaddr_union_pppox link = {
569 .pppox = {
570 .sa_family = AF_PPPOX,
571 .sa_protocol = PX_PROTO_OE,
572 },
573 };
574 int r, channel;
575
576 assert(ppp);
577 assert(ppp->pppoe_fd != -1);
578 assert(ppp->session_id);
579 assert(ppp->ifname);
580
581 link.pppox.sa_addr.pppoe.sid = ppp->session_id;
582 memcpy(link.pppox.sa_addr.pppoe.dev, ppp->ifname, strlen(ppp->ifname));
583 memcpy(link.pppox.sa_addr.pppoe.remote, &ppp->peer_mac, ETH_ALEN);
584
585 r = connect(ppp->pppoe_fd, &link.sa, sizeof(link.pppox));
586 if (r < 0)
587 return r;
588
589 r = ioctl(ppp->pppoe_fd, PPPIOCGCHAN, &channel);
590 if (r < 0)
591 return -errno;
592
593 ppp->channel = channel;
594
595 return 0;
596}
597
598static int pppoe_handle_message(sd_pppoe *ppp, struct pppoe_hdr *packet, struct ether_addr *mac) {
599 int r;
600
601 assert(packet);
602
603 if (packet->ver != 0x1 || packet->type != 0x1)
604 return 0;
605
606 r = pppoe_payload_parse(&ppp->tags, packet);
607 if (r < 0)
608 return 0;
609
610 switch (ppp->state) {
611 case PPPOE_STATE_INITIALIZING:
612 if (packet->code != PADO_CODE)
613 return 0;
614
615 if (ppp->tags.host_uniq_len != sizeof(ppp->host_uniq) ||
616 memcmp(ppp->tags.host_uniq, &ppp->host_uniq, sizeof(ppp->host_uniq)) != 0)
617 return 0;
618
619 log_debug("PPPoE: got OFFER (Peer: "
620 "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx; "
621 "Service-Name: '%s'; AC-Name: '%s')",
622 mac->ether_addr_octet[0],
623 mac->ether_addr_octet[1],
624 mac->ether_addr_octet[2],
625 mac->ether_addr_octet[3],
626 mac->ether_addr_octet[4],
627 mac->ether_addr_octet[5],
5cfee414
DM
628 strempty(ppp->tags.service_name),
629 strempty(ppp->tags.ac_name));
cda391c3
TG
630
631 memcpy(&ppp->peer_mac, mac, ETH_ALEN);
632
633 r = pppoe_open_pppoe_socket(ppp);
634 if (r < 0) {
635 log_warning("PPPoE: could not open socket");
636 return r;
637 }
638
639 r = pppoe_send_request(ppp);
640 if (r < 0)
641 return 0;
642
643 ppp->state = PPPOE_STATE_REQUESTING;
644
645 break;
646 case PPPOE_STATE_REQUESTING:
647 if (packet->code != PADS_CODE)
648 return 0;
649
650 if (ppp->tags.host_uniq_len != sizeof(ppp->host_uniq) ||
651 memcmp(ppp->tags.host_uniq, &ppp->host_uniq,
652 sizeof(ppp->host_uniq)) != 0)
653 return 0;
654
655 if (memcmp(&ppp->peer_mac, mac, ETH_ALEN) != 0)
656 return 0;
657
658 ppp->session_id = packet->sid;
659
660 log_debug("PPPoE: got CONFIRMATION (Session ID: %"PRIu16")",
661 be16toh(ppp->session_id));
662
663 r = pppoe_connect_pppoe_socket(ppp);
664 if (r < 0) {
665 log_warning("PPPoE: could not connect socket");
666 return r;
667 }
668
669 ppp->state = PPPOE_STATE_RUNNING;
670
671 ppp->timeout = sd_event_source_unref(ppp->timeout);
672 assert(ppp->cb);
e4c3b8e8 673 ppp->cb(ppp, SD_PPPOE_EVENT_RUNNING, ppp->userdata);
cda391c3
TG
674
675 break;
676 case PPPOE_STATE_RUNNING:
677 if (packet->code != PADT_CODE)
678 return 0;
679
680 if (memcmp(&ppp->peer_mac, mac, ETH_ALEN) != 0)
681 return 0;
682
683 if (ppp->session_id != packet->sid)
684 return 0;
685
686 log_debug("PPPoE: got TERMINATE");
687
688 ppp->state = PPPOE_STATE_STOPPED;
689
690 assert(ppp->cb);
e4c3b8e8 691 ppp->cb(ppp, SD_PPPOE_EVENT_STOPPED, ppp->userdata);
cda391c3
TG
692
693 break;
694 case PPPOE_STATE_STOPPED:
695 break;
696 default:
697 assert_not_reached("PPPoE: invalid state when receiving message");
698 }
699
700 return 0;
701}
702
9eec6713 703static int pppoe_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
cda391c3
TG
704 sd_pppoe *ppp = userdata;
705 _cleanup_free_ struct pppoe_hdr *packet = NULL;
706 union sockaddr_union link = {};
707 socklen_t addrlen = sizeof(link);
708 int buflen = 0, len, r;
709
710 assert(ppp);
711 assert(fd != -1);
712
713 r = ioctl(fd, FIONREAD, &buflen);
714 if (r < 0)
715 return r;
716
717 if (buflen < 0)
718 /* this can't be right */
719 return -EIO;
720
721 packet = malloc0(buflen);
722 if (!packet)
723 return -ENOMEM;
724
9eec6713 725 len = recvfrom(fd, packet, buflen, 0, &link.sa, &addrlen);
cda391c3 726 if (len < 0) {
da927ba9 727 log_warning_errno(r, "PPPoE: could not receive message from raw socket: %m");
cda391c3
TG
728 return 0;
729 } else if ((size_t)len < sizeof(struct pppoe_hdr))
730 return 0;
731 else if ((size_t)len != sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet))
732 return 0;
733
734 if (link.ll.sll_halen != ETH_ALEN)
735 /* not ethernet? */
736 return 0;
737
738 r = pppoe_handle_message(ppp, packet, (struct ether_addr*)&link.ll.sll_addr);
739 if (r < 0)
740 return r;
741
742 return 1;
743}
744
745int sd_pppoe_start(sd_pppoe *ppp) {
746 union sockaddr_union link = {
747 .ll = {
748 .sll_family = AF_PACKET,
749 .sll_protocol = htons(ETH_P_PPP_DISC),
750 },
751 };
752 _cleanup_close_ int s = -1;
753 _cleanup_event_source_unref_ sd_event_source *io = NULL;
754 int r;
755
756 assert_return(ppp, -EINVAL);
757 assert_return(ppp->fd == -1, -EBUSY);
758 assert_return(!ppp->io, -EBUSY);
759 assert_return(ppp->ifindex > 0, -EUNATCH);
760 assert_return(ppp->ifname, -EUNATCH);
761 assert_return(ppp->event, -EUNATCH);
762 assert_return(ppp->cb, -EUNATCH);
763
764 s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
765 if (s < 0)
766 return -errno;
767
768 link.ll.sll_ifindex = ppp->ifindex;
769
770 r = bind(s, &link.sa, sizeof(link.ll));
771 if (r < 0)
772 return r;
773
774 r = sd_event_add_io(ppp->event, &io,
775 s, EPOLLIN, pppoe_receive_message,
776 ppp);
777 if (r < 0)
778 return r;
779
780 r = sd_event_source_set_priority(io, ppp->event_priority);
781 if (r < 0)
782 return r;
783
784 ppp->fd = s;
785 s = -1;
786 ppp->io = io;
787 io = NULL;
788
789 r = pppoe_send_initiation(ppp);
790 if (r < 0)
791 return r;
792
793 ppp->state = PPPOE_STATE_INITIALIZING;
794
795 return 0;
796}
797
798int sd_pppoe_stop(sd_pppoe *ppp) {
799 assert_return(ppp, -EINVAL);
800
801 if (ppp->state == PPPOE_STATE_RUNNING)
802 pppoe_send_terminate(ppp);
803
804 ppp->io = sd_event_source_unref(ppp->io);
805 ppp->timeout = sd_event_source_unref(ppp->timeout);
806 ppp->fd = asynchronous_close(ppp->fd);
807 ppp->pppoe_fd = asynchronous_close(ppp->pppoe_fd);
808
809 return 0;
810}