]> git.ipfire.org Git - thirdparty/systemd.git/blob - 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
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 "string-util.h"
38 #include "utf8.h"
39 #include "util.h"
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 */
46 union sockaddr_union_pppox {
47 struct sockaddr sa;
48 struct sockaddr_pppox pppox;
49 };
50
51 typedef 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
60 typedef 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
69 struct sd_pppoe {
70 unsigned n_ref;
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) \
102 (struct pppoe_tag*)((uint8_t*)(packet) + sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet))
103
104 #define PPPOE_TAG_LENGTH(tag) \
105 be16toh((tag)->tag_len)
106
107 #define PPPOE_TAG_TYPE(tag) \
108 (tag)->tag_type
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
121 static 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
130 int 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
139 int 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
158 int 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
176 int 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
195 int 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
203 sd_pppoe *sd_pppoe_ref(sd_pppoe *ppp) {
204
205 if (!ppp)
206 return NULL;
207
208 assert(ppp->n_ref > 0);
209 ppp->n_ref++;
210
211 return ppp;
212 }
213
214 sd_pppoe *sd_pppoe_unref(sd_pppoe *ppp) {
215
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);
232 return NULL;
233 }
234
235 int 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
244 ppp->n_ref = 1;
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
256 int 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
267 int 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
276 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) {
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
285 tag->tag_len = htobe16(tag_len);
286 tag->tag_type = tag_type;
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
293 static 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
349 static int pppoe_timeout(sd_event_source *s, uint64_t usec, void *userdata);
350
351 static int pppoe_arm_timeout(sd_pppoe *ppp) {
352 _cleanup_event_source_unref_ sd_event_source *timeout = NULL;
353 usec_t next_timeout = 0;
354 int r;
355
356 assert(ppp);
357
358 r = sd_event_now(ppp->event, clock_boottime_or_monotonic(), &next_timeout);
359 if (r < 0)
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
380 static 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)",
388 strna(ppp->service_name));
389
390 pppoe_arm_timeout(ppp);
391
392 return r;
393 }
394
395 static 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
411 static 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
423 static 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)
433 log_warning_errno(r, "PPPoE: sending PADI failed: %m");
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)
442 log_warning_errno(r, "PPPoE: sending PADI failed: %m");
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)
449 log_warning_errno(r, "PPPoE: sending PADR failed: %m");
450 }
451
452 break;
453 default:
454 assert_not_reached("timeout in invalid state");
455 }
456
457 return 0;
458 }
459
460 static 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
477 static 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
492 static 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
552 static 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
567 static 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
598 static 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],
628 strempty(ppp->tags.service_name),
629 strempty(ppp->tags.ac_name));
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);
673 ppp->cb(ppp, SD_PPPOE_EVENT_RUNNING, ppp->userdata);
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);
691 ppp->cb(ppp, SD_PPPOE_EVENT_STOPPED, ppp->userdata);
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
703 static int pppoe_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
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
725 len = recvfrom(fd, packet, buflen, 0, &link.sa, &addrlen);
726 if (len < 0) {
727 log_warning_errno(r, "PPPoE: could not receive message from raw socket: %m");
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
745 int 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
798 int 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 }