chiark / gitweb /
update TODO
[elogind.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 <sys/ioctl.h>
25 #include <linux/ppp_defs.h>
26 #include <linux/ppp-ioctl.h>
27 #include <net/if.h>
28 #include <netinet/in.h>
29 #include <linux/if_pppox.h>
30
31 #include "sd-pppoe.h"
32
33 #include "event-util.h"
34
35 #include "util.h"
36 #include "socket-util.h"
37 #include "async.h"
38 #include "refcnt.h"
39 #include "unaligned.h"
40 #include "utf8.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         RefCount 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         if (ppp)
206                 assert_se(REFCNT_INC(ppp->n_ref) >= 2);
207
208         return ppp;
209 }
210
211 sd_pppoe *sd_pppoe_unref(sd_pppoe *ppp) {
212         if (ppp && REFCNT_DEC(ppp->n_ref) <= 0) {
213                 pppoe_tags_clear(&ppp->tags);
214                 free(ppp->ifname);
215                 free(ppp->service_name);
216                 sd_pppoe_stop(ppp);
217                 sd_pppoe_detach_event(ppp);
218
219                 free(ppp);
220         }
221
222         return NULL;
223 }
224
225 int sd_pppoe_new (sd_pppoe **ret) {
226         sd_pppoe *ppp;
227
228         assert_return(ret, -EINVAL);
229
230         ppp = new0(sd_pppoe, 1);
231         if (!ppp)
232                 return -ENOMEM;
233
234         ppp->n_ref = REFCNT_INIT;
235         ppp->state = _PPPOE_STATE_INVALID;
236         ppp->ifindex = -1;
237         ppp->fd = -1;
238         ppp->pppoe_fd = -1;
239         ppp->padr_resend_count = PPPOE_MAX_PADR_RESEND;
240
241         *ret = ppp;
242
243         return 0;
244 }
245
246 int sd_pppoe_get_channel(sd_pppoe *ppp, int *channel) {
247         assert_return(ppp, -EINVAL);
248         assert_return(channel, -EINVAL);
249         assert_return(ppp->pppoe_fd != -1, -EUNATCH);
250         assert_return(ppp->state == PPPOE_STATE_RUNNING, -EUNATCH);
251
252         *channel = ppp->channel;
253
254         return 0;
255 }
256
257 int sd_pppoe_set_callback(sd_pppoe *ppp, sd_pppoe_cb_t cb, void *userdata) {
258         assert_return(ppp, -EINVAL);
259
260         ppp->cb = cb;
261         ppp->userdata = userdata;
262
263         return 0;
264 }
265
266 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) {
267         struct pppoe_tag *tag;
268
269         assert(packet);
270         assert(sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet) + sizeof(struct pppoe_tag) + tag_len <= packet_size);
271         assert(!(!tag_data ^ !tag_len));
272
273         tag = PPPOE_PACKET_TAIL(packet);
274
275         tag->tag_len = htobe16(tag_len);
276         tag->tag_type = tag_type;
277         if (tag_data)
278                 memcpy(tag->tag_data, tag_data, tag_len);
279
280         packet->length = htobe16(PPPOE_PACKET_LENGTH(packet) + sizeof(struct pppoe_tag) + tag_len);
281 }
282
283 static int pppoe_send(sd_pppoe *ppp, uint8_t code) {
284         union sockaddr_union link = {
285                 .ll = {
286                         .sll_family = AF_PACKET,
287                         .sll_protocol = htons(ETH_P_PPP_DISC),
288                         .sll_halen = ETH_ALEN,
289                 },
290         };
291         _cleanup_free_ struct pppoe_hdr *packet = NULL;
292         int r;
293
294         assert(ppp);
295         assert(ppp->fd != -1);
296         assert(IN_SET(code, PADI_CODE, PADR_CODE, PADT_CODE));
297
298         link.ll.sll_ifindex = ppp->ifindex;
299         if (code == PADI_CODE)
300                 memset(&link.ll.sll_addr, 0xff, ETH_ALEN);
301         else
302                 memcpy(&link.ll.sll_addr, &ppp->peer_mac, ETH_ALEN);
303
304         packet = malloc0(PPPOE_MAX_PACKET_SIZE);
305         if (!packet)
306                 return -ENOMEM;
307
308         packet->ver = 0x1;
309         packet->type = 0x1;
310         packet->code = code;
311         if (code == PADT_CODE)
312                 packet->sid = ppp->session_id;
313
314         /* Service-Name */
315         pppoe_tag_append(packet, PPPOE_MAX_PACKET_SIZE, PTT_SRV_NAME,
316                          ppp->service_name, ppp->service_name ? strlen(ppp->service_name) : 0);
317
318         /* AC-Cookie */
319         if (code == PADR_CODE && ppp->tags.cookie)
320                 pppoe_tag_append(packet, PPPOE_MAX_PACKET_SIZE, PTT_AC_COOKIE,
321                                  ppp->tags.cookie, ppp->tags.cookie_len);
322
323         /* Host-Uniq */
324         if (code != PADT_CODE) {
325                 ppp->host_uniq = random_u64();
326
327                 pppoe_tag_append(packet, PPPOE_MAX_PACKET_SIZE, PTT_HOST_UNIQ,
328                                  &ppp->host_uniq, sizeof(ppp->host_uniq));
329         }
330
331         r = sendto(ppp->fd, packet, sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet),
332                    0, &link.sa, sizeof(link.ll));
333         if (r < 0)
334                 return -errno;
335
336         return 0;
337 }
338
339 static int pppoe_timeout(sd_event_source *s, uint64_t usec, void *userdata);
340
341 static int pppoe_arm_timeout(sd_pppoe *ppp) {
342         _cleanup_event_source_unref_ sd_event_source *timeout = NULL;
343         usec_t next_timeout;
344         int r;
345
346         assert(ppp);
347
348         r = sd_event_now(ppp->event, clock_boottime_or_monotonic(), &next_timeout);
349         if (r == -ENODATA)
350                 next_timeout = now(clock_boottime_or_monotonic());
351         else if (r < 0)
352                 return r;
353
354         next_timeout += 500 * USEC_PER_MSEC;
355
356         r = sd_event_add_time(ppp->event, &timeout, clock_boottime_or_monotonic(), next_timeout,
357                               10 * USEC_PER_MSEC, pppoe_timeout, ppp);
358         if (r < 0)
359                 return r;
360
361         r = sd_event_source_set_priority(timeout, ppp->event_priority);
362         if (r < 0)
363                 return r;
364
365         sd_event_source_unref(ppp->timeout);
366         ppp->timeout = timeout;
367         timeout = NULL;
368
369         return 0;
370 }
371
372 static int pppoe_send_initiation(sd_pppoe *ppp) {
373         int r;
374
375         r = pppoe_send(ppp, PADI_CODE);
376         if (r < 0)
377                 return r;
378
379         log_debug("PPPoE: sent DISCOVER (Service-Name: %s)",
380                   ppp->service_name ? : "");
381
382         pppoe_arm_timeout(ppp);
383
384         return r;
385 }
386
387 static int pppoe_send_request(sd_pppoe *ppp) {
388         int r;
389
390         r = pppoe_send(ppp, PADR_CODE);
391         if (r < 0)
392                 return r;
393
394         log_debug("PPPoE: sent REQUEST");
395
396         ppp->padr_resend_count --;
397
398         pppoe_arm_timeout(ppp);
399
400         return 0;
401 }
402
403 static int pppoe_send_terminate(sd_pppoe *ppp) {
404         int r;
405
406         r = pppoe_send(ppp, PADT_CODE);
407         if (r < 0)
408                 return r;
409
410         log_debug("PPPoE: sent TERMINATE");
411
412         return 0;
413 }
414
415 static int pppoe_timeout(sd_event_source *s, uint64_t usec, void *userdata) {
416         sd_pppoe *ppp = userdata;
417         int r;
418
419         assert(ppp);
420
421         switch (ppp->state) {
422         case PPPOE_STATE_INITIALIZING:
423                 r = pppoe_send_initiation(ppp);
424                 if (r < 0)
425                         log_warning_errno(r, "PPPoE: sending PADI failed: %m");
426
427                 break;
428         case PPPOE_STATE_REQUESTING:
429                 if (ppp->padr_resend_count <= 0) {
430                         log_debug("PPPoE: PADR timed out, restarting PADI");
431
432                         r = pppoe_send_initiation(ppp);
433                         if (r < 0)
434                                 log_warning_errno(r, "PPPoE: sending PADI failed: %m");
435
436                         ppp->padr_resend_count = PPPOE_MAX_PADR_RESEND;
437                         ppp->state = PPPOE_STATE_INITIALIZING;
438                 } else {
439                         r = pppoe_send_request(ppp);
440                         if (r < 0)
441                                 log_warning_errno(r, "PPPoE: sending PADR failed: %m");
442                 }
443
444                 break;
445         default:
446                 assert_not_reached("timeout in invalid state");
447         }
448
449         return 0;
450 }
451
452 static int pppoe_tag_parse_binary(struct pppoe_tag *tag, uint8_t **ret, size_t *length) {
453         uint8_t *data;
454
455         assert(ret);
456         assert(length);
457
458         data = memdup(tag->tag_data, PPPOE_TAG_LENGTH(tag));
459         if (!data)
460                 return -ENOMEM;
461
462         free(*ret);
463         *ret = data;
464         *length = PPPOE_TAG_LENGTH(tag);
465
466         return 0;
467 }
468
469 static int pppoe_tag_parse_string(struct pppoe_tag *tag, char **ret) {
470         char *string;
471
472         assert(ret);
473
474         string = strndup(tag->tag_data, PPPOE_TAG_LENGTH(tag));
475         if (!string)
476                 return -ENOMEM;
477
478         free(*ret);
479         *ret = string;
480
481         return 0;
482 }
483
484 static int pppoe_payload_parse(PPPoETags *tags, struct pppoe_hdr *header) {
485         struct pppoe_tag *tag;
486         int r;
487
488         assert(tags);
489
490         pppoe_tags_clear(tags);
491
492         PPPOE_TAGS_FOREACH(tag, header) {
493                 switch (PPPOE_TAG_TYPE(tag)) {
494                 case PTT_SRV_NAME:
495                         r = pppoe_tag_parse_string(tag, &tags->service_name);
496                         if (r < 0)
497                                 return r;
498
499                         break;
500                 case PTT_AC_NAME:
501                         r = pppoe_tag_parse_string(tag, &tags->ac_name);
502                         if (r < 0)
503                                 return r;
504
505                         break;
506                 case PTT_HOST_UNIQ:
507                         r = pppoe_tag_parse_binary(tag, &tags->host_uniq, &tags->host_uniq_len);
508                         if (r < 0)
509                                 return r;
510
511                         break;
512                 case PTT_AC_COOKIE:
513                         r = pppoe_tag_parse_binary(tag, &tags->cookie, &tags->cookie_len);
514                         if (r < 0)
515                                 return r;
516
517                         break;
518                 case PTT_SRV_ERR:
519                 case PTT_SYS_ERR:
520                 case PTT_GEN_ERR:
521                 {
522                         _cleanup_free_ char *error = NULL;
523
524                         /* TODO: do something more sensible with the error messages */
525                         r = pppoe_tag_parse_string(tag, &error);
526                         if (r < 0)
527                                 return r;
528
529                         if (strlen(error) > 0 && utf8_is_valid(error))
530                                 log_debug("PPPoE: error - '%s'", error);
531                         else
532                                 log_debug("PPPoE: error");
533
534                         break;
535                 }
536                 default:
537                         log_debug("PPPoE: ignoring unknown PPPoE tag type: 0x%.2x", PPPOE_TAG_TYPE(tag));
538                 }
539         }
540
541         return 0;
542 }
543
544 static int pppoe_open_pppoe_socket(sd_pppoe *ppp) {
545         int s;
546
547         assert(ppp);
548         assert(ppp->pppoe_fd == -1);
549
550         s = socket(AF_PPPOX, SOCK_STREAM, 0);
551         if (s < 0)
552                 return -errno;
553
554         ppp->pppoe_fd = s;
555
556         return 0;
557 }
558
559 static int pppoe_connect_pppoe_socket(sd_pppoe *ppp) {
560         union sockaddr_union_pppox link = {
561                 .pppox = {
562                         .sa_family = AF_PPPOX,
563                         .sa_protocol = PX_PROTO_OE,
564                 },
565         };
566         int r, channel;
567
568         assert(ppp);
569         assert(ppp->pppoe_fd != -1);
570         assert(ppp->session_id);
571         assert(ppp->ifname);
572
573         link.pppox.sa_addr.pppoe.sid = ppp->session_id;
574         memcpy(link.pppox.sa_addr.pppoe.dev, ppp->ifname, strlen(ppp->ifname));
575         memcpy(link.pppox.sa_addr.pppoe.remote, &ppp->peer_mac, ETH_ALEN);
576
577         r = connect(ppp->pppoe_fd, &link.sa, sizeof(link.pppox));
578         if (r < 0)
579                 return r;
580
581         r = ioctl(ppp->pppoe_fd, PPPIOCGCHAN, &channel);
582         if (r < 0)
583                 return -errno;
584
585         ppp->channel = channel;
586
587         return 0;
588 }
589
590 static int pppoe_handle_message(sd_pppoe *ppp, struct pppoe_hdr *packet, struct ether_addr *mac) {
591         int r;
592
593         assert(packet);
594
595         if (packet->ver != 0x1 || packet->type != 0x1)
596                 return 0;
597
598         r = pppoe_payload_parse(&ppp->tags, packet);
599         if (r < 0)
600                 return 0;
601
602         switch (ppp->state) {
603         case PPPOE_STATE_INITIALIZING:
604                 if (packet->code != PADO_CODE)
605                         return 0;
606
607                 if (ppp->tags.host_uniq_len != sizeof(ppp->host_uniq) ||
608                     memcmp(ppp->tags.host_uniq, &ppp->host_uniq, sizeof(ppp->host_uniq)) != 0)
609                         return 0;
610
611                 log_debug("PPPoE: got OFFER (Peer: "
612                   "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx; "
613                   "Service-Name: '%s'; AC-Name: '%s')",
614                   mac->ether_addr_octet[0],
615                   mac->ether_addr_octet[1],
616                   mac->ether_addr_octet[2],
617                   mac->ether_addr_octet[3],
618                   mac->ether_addr_octet[4],
619                   mac->ether_addr_octet[5],
620                   ppp->tags.service_name ? : "",
621                   ppp->tags.ac_name ? : "");
622
623                 memcpy(&ppp->peer_mac, mac, ETH_ALEN);
624
625                 r = pppoe_open_pppoe_socket(ppp);
626                 if (r < 0) {
627                         log_warning("PPPoE: could not open socket");
628                         return r;
629                 }
630
631                 r = pppoe_send_request(ppp);
632                 if (r < 0)
633                         return 0;
634
635                 ppp->state = PPPOE_STATE_REQUESTING;
636
637                 break;
638         case PPPOE_STATE_REQUESTING:
639                 if (packet->code != PADS_CODE)
640                         return 0;
641
642                 if (ppp->tags.host_uniq_len != sizeof(ppp->host_uniq) ||
643                     memcmp(ppp->tags.host_uniq, &ppp->host_uniq,
644                            sizeof(ppp->host_uniq)) != 0)
645                         return 0;
646
647                 if (memcmp(&ppp->peer_mac, mac, ETH_ALEN) != 0)
648                         return 0;
649
650                 ppp->session_id = packet->sid;
651
652                 log_debug("PPPoE: got CONFIRMATION (Session ID: %"PRIu16")",
653                           be16toh(ppp->session_id));
654
655                 r = pppoe_connect_pppoe_socket(ppp);
656                 if (r < 0) {
657                         log_warning("PPPoE: could not connect socket");
658                         return r;
659                 }
660
661                 ppp->state = PPPOE_STATE_RUNNING;
662
663                 ppp->timeout = sd_event_source_unref(ppp->timeout);
664                 assert(ppp->cb);
665                 ppp->cb(ppp, PPPOE_EVENT_RUNNING, ppp->userdata);
666
667                 break;
668         case PPPOE_STATE_RUNNING:
669                 if (packet->code != PADT_CODE)
670                         return 0;
671
672                 if (memcmp(&ppp->peer_mac, mac, ETH_ALEN) != 0)
673                         return 0;
674
675                 if (ppp->session_id != packet->sid)
676                         return 0;
677
678                 log_debug("PPPoE: got TERMINATE");
679
680                 ppp->state = PPPOE_STATE_STOPPED;
681
682                 assert(ppp->cb);
683                 ppp->cb(ppp, PPPOE_EVENT_STOPPED, ppp->userdata);
684
685                 break;
686         case PPPOE_STATE_STOPPED:
687                 break;
688         default:
689                 assert_not_reached("PPPoE: invalid state when receiving message");
690         }
691
692         return 0;
693 }
694
695 static int pppoe_receive_message(sd_event_source *s, int fd, uint32_t revents, void *userdata) {
696         sd_pppoe *ppp = userdata;
697         _cleanup_free_ struct pppoe_hdr *packet = NULL;
698         union sockaddr_union link = {};
699         socklen_t addrlen = sizeof(link);
700         int buflen = 0, len, r;
701
702         assert(ppp);
703         assert(fd != -1);
704
705         r = ioctl(fd, FIONREAD, &buflen);
706         if (r < 0)
707                 return r;
708
709         if (buflen < 0)
710                 /* this can't be right */
711                 return -EIO;
712
713         packet = malloc0(buflen);
714         if (!packet)
715                 return -ENOMEM;
716
717         len = recvfrom(fd, packet, buflen, 0, &link.sa, &addrlen);
718         if (len < 0) {
719                 log_warning_errno(r, "PPPoE: could not receive message from raw socket: %m");
720                 return 0;
721         } else if ((size_t)len < sizeof(struct pppoe_hdr))
722                 return 0;
723         else if ((size_t)len != sizeof(struct pppoe_hdr) + PPPOE_PACKET_LENGTH(packet))
724                 return 0;
725
726         if (link.ll.sll_halen != ETH_ALEN)
727                 /* not ethernet? */
728                 return 0;
729
730         r = pppoe_handle_message(ppp, packet, (struct ether_addr*)&link.ll.sll_addr);
731         if (r < 0)
732                 return r;
733
734         return 1;
735 }
736
737 int sd_pppoe_start(sd_pppoe *ppp) {
738         union sockaddr_union link = {
739                 .ll = {
740                         .sll_family = AF_PACKET,
741                         .sll_protocol = htons(ETH_P_PPP_DISC),
742                 },
743         };
744         _cleanup_close_ int s = -1;
745         _cleanup_event_source_unref_ sd_event_source *io = NULL;
746         int r;
747
748         assert_return(ppp, -EINVAL);
749         assert_return(ppp->fd == -1, -EBUSY);
750         assert_return(!ppp->io, -EBUSY);
751         assert_return(ppp->ifindex > 0, -EUNATCH);
752         assert_return(ppp->ifname, -EUNATCH);
753         assert_return(ppp->event, -EUNATCH);
754         assert_return(ppp->cb, -EUNATCH);
755
756         s = socket(AF_PACKET, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0);
757         if (s < 0)
758                 return -errno;
759
760         link.ll.sll_ifindex = ppp->ifindex;
761
762         r = bind(s, &link.sa, sizeof(link.ll));
763         if (r < 0)
764                 return r;
765
766         r = sd_event_add_io(ppp->event, &io,
767                             s, EPOLLIN, pppoe_receive_message,
768                             ppp);
769         if (r < 0)
770                 return r;
771
772         r = sd_event_source_set_priority(io, ppp->event_priority);
773         if (r < 0)
774                 return r;
775
776         ppp->fd = s;
777         s = -1;
778         ppp->io = io;
779         io = NULL;
780
781         r = pppoe_send_initiation(ppp);
782         if (r < 0)
783                 return r;
784
785         ppp->state = PPPOE_STATE_INITIALIZING;
786
787         return 0;
788 }
789
790 int sd_pppoe_stop(sd_pppoe *ppp) {
791         assert_return(ppp, -EINVAL);
792
793         if (ppp->state == PPPOE_STATE_RUNNING)
794                 pppoe_send_terminate(ppp);
795
796         ppp->io = sd_event_source_unref(ppp->io);
797         ppp->timeout = sd_event_source_unref(ppp->timeout);
798         ppp->fd = asynchronous_close(ppp->fd);
799         ppp->pppoe_fd = asynchronous_close(ppp->pppoe_fd);
800
801         return 0;
802 }