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