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