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