summaryrefslogtreecommitdiff
path: root/usr.sbin/pppoe/common.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/pppoe/common.c')
-rw-r--r--usr.sbin/pppoe/common.c293
1 files changed, 293 insertions, 0 deletions
diff --git a/usr.sbin/pppoe/common.c b/usr.sbin/pppoe/common.c
new file mode 100644
index 00000000000..e47537bbb0f
--- /dev/null
+++ b/usr.sbin/pppoe/common.c
@@ -0,0 +1,293 @@
+/* $OpenBSD: common.c,v 1.1 2000/06/18 07:30:41 jason Exp $ */
+
+/*
+ * Copyright (c) 2000 Network Security Technologies, Inc. http://www.netsec.net
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Network Security
+ * Technologies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/ppp_defs.h>
+#include <netinet/in.h>
+#include <netinet/if_ether.h>
+#include <net/bpf.h>
+#include <errno.h>
+#include <string.h>
+#include <err.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sysexits.h>
+#include <stdlib.h>
+#include <grp.h>
+#include <syslog.h>
+#include <md5.h>
+
+#include "pppoe.h"
+
+#define PPP_PROG "/usr/sbin/ppp"
+
+void debugv __P((char *, struct iovec *, int));
+
+int
+runppp(bpffd, sysname)
+ int bpffd;
+ char *sysname;
+{
+ int socks[2], fdm, fds, closeit;
+ pid_t pid;
+
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, socks) < 0)
+ return (-1);
+
+ fdm = socks[0];
+ fds = socks[1];
+
+ pid = fork();
+ if (pid < 0) {
+ close(fds);
+ close(fdm);
+ return (-1);
+ }
+
+ if (pid != 0) {
+ /* Parent */
+ close(fds);
+ return (fdm);
+ }
+
+ if (setsid() < 0)
+ _exit(99);
+
+ /* Child */
+ close(bpffd);
+ close(fdm);
+ closeit = 1;
+
+ if (fds == STDIN_FILENO)
+ closeit = 0;
+ else
+ dup2(fds, STDIN_FILENO);
+
+ if (fds == STDOUT_FILENO)
+ closeit = 0;
+ else
+ dup2(fds, STDOUT_FILENO);
+
+ if (fds == STDERR_FILENO)
+ closeit = 0;
+ else
+ dup2(fds, STDERR_FILENO);
+
+ if (closeit)
+ close(fds);
+
+ execlp(PPP_PROG, "ppp", "-direct", sysname, NULL);
+ perror("execlp");
+ syslog(LOG_INFO, "%s exec failed: %m", PPP_PROG);
+ _exit(-1);
+}
+
+int
+bpf_to_ppp(pppfd, len, pkt)
+ int pppfd;
+ u_long len;
+ u_int8_t *pkt;
+{
+ int r;
+ u_int8_t hdr[2] = { PPP_ALLSTATIONS, PPP_UI };
+ struct iovec iov[2];
+
+ iov[0].iov_base = hdr;
+ iov[0].iov_len = sizeof(hdr);
+ iov[1].iov_base = pkt;
+ iov[1].iov_len = len;
+
+ r = writev(pppfd, iov, 2);
+ if (r < 0) {
+ if (errno == EINTR || errno == EPIPE)
+ return (0);
+ return (-1);
+ }
+ return (1);
+}
+
+int
+ppp_to_bpf(bfd, pppfd, myea, rmea, id)
+ int bfd, pppfd;
+ struct ether_addr *myea, *rmea;
+ u_int16_t id;
+{
+ static u_int8_t *pktbuf = NULL;
+ struct pppoe_header ph;
+ struct iovec iov[5];
+ u_int16_t etype;
+ u_int8_t trash[2];
+ int r;
+
+ if (pktbuf == NULL) {
+ pktbuf = (u_int8_t *)malloc(PPPOE_MTU);
+ if (pktbuf == NULL)
+ return (-1);
+ }
+
+ iov[0].iov_base = trash;
+ iov[0].iov_len = 2;
+ iov[1].iov_base = pktbuf;
+ iov[1].iov_len = PPPOE_MTU;
+ r = readv(pppfd, iov, 2);
+ if (r <= 0)
+ return (-1);
+ r -= 2;
+
+ iov[0].iov_len = 2;
+ iov[1].iov_len = r;
+
+ ph.vertype = PPPOE_VERTYPE(1, 1);
+ ph.code = PPPOE_CODE_SESSION;
+ ph.len = htons(r);
+ ph.sessionid = htons(id);
+ etype = htons(ETHERTYPE_PPPOE);
+
+ iov[0].iov_base = rmea; iov[0].iov_len = ETHER_ADDR_LEN;
+ iov[1].iov_base = myea; iov[1].iov_len = ETHER_ADDR_LEN;
+ iov[2].iov_base = &etype; iov[2].iov_len = sizeof(etype);
+ iov[3].iov_base = &ph; iov[3].iov_len = sizeof(ph);
+ iov[4].iov_base = pktbuf; iov[4].iov_len = r;
+
+ return (writev(bfd, iov, 5));
+}
+
+void
+debugv(s, iov, cnt)
+ char *s;
+ struct iovec *iov;
+ int cnt;
+{
+ int i, j;
+ u_int8_t *p;
+
+ printf("%s", s);
+ for (i = 0; i < cnt; i++)
+ for (j = 0; j < iov[i].iov_len; j++) {
+ p = (u_int8_t *)iov[i].iov_base;
+ printf("%02x:", p[j]);
+ }
+ printf("\n\n");
+}
+
+void
+recv_debug(bpffd, ea, eh, ph, pktlen, pktbuf)
+ int bpffd;
+ struct ether_addr *ea;
+ struct ether_header *eh;
+ struct pppoe_header *ph;
+ u_long pktlen;
+ u_int8_t *pktbuf;
+{
+ struct tag_list tl;
+
+ printf("dst %02x:%02x:%02x:%02x:%02x:%02x, "
+ "src %02x:%02x:%02x:%02x:%02x:%02x, type %04x\n",
+ eh->ether_dhost[0], eh->ether_dhost[1], eh->ether_dhost[2],
+ eh->ether_dhost[3], eh->ether_dhost[4], eh->ether_dhost[5],
+ eh->ether_shost[0], eh->ether_shost[1], eh->ether_shost[2],
+ eh->ether_shost[3], eh->ether_shost[4], eh->ether_shost[5],
+ eh->ether_type);
+ printf("\tver %d, type %d, code %02x, id %04x, len %d\n",
+ PPPOE_VER(ph->vertype), PPPOE_TYPE(ph->vertype),
+ ph->code, ph->sessionid, ph->len);
+
+ tag_init(&tl);
+ if (tag_pkt(&tl, pktlen, pktbuf) < 0) {
+ printf("bad tag pkt\n");
+ goto out;
+ }
+
+ tag_show(&tl);
+out:
+ tag_destroy(&tl);
+}
+
+int
+send_padt(bpffd, src_ea, dst_ea, id)
+ int bpffd;
+ struct ether_addr *src_ea, *dst_ea;
+ u_int16_t id;
+{
+ struct iovec iov[4];
+ struct pppoe_header ph;
+ u_int16_t etype = htons(ETHERTYPE_PPPOEDISC);
+
+ iov[0].iov_base = dst_ea;
+ iov[0].iov_len = ETHER_ADDR_LEN;
+ iov[1].iov_base = src_ea;
+ iov[1].iov_len = ETHER_ADDR_LEN;
+ iov[2].iov_base = &etype;
+ iov[2].iov_len = sizeof(etype);
+ iov[3].iov_base = &ph;
+ iov[3].iov_len = sizeof(ph);
+
+ ph.vertype = PPPOE_VERTYPE(1, 1);
+ ph.code = PPPOE_CODE_PADT;
+ ph.len = 0;
+ ph.sessionid = htons(id);
+
+ return (writev(bpffd, iov, 4));
+}
+
+u_int32_t
+cookie_bake()
+{
+ MD5_CTX ctx;
+ char buf[40];
+ u_int32_t x, y;
+
+ x = arc4random();
+ MD5Init(&ctx);
+ MD5Update(&ctx, (unsigned char *)&x, sizeof(x));
+ MD5Final(buf, &ctx);
+ bcopy(buf, &y, sizeof(y));
+ x = x ^ y;
+ bcopy(buf + 4, &y, sizeof(y));
+ x = x ^ y;
+ bcopy(buf + 8, &y, sizeof(y));
+ x = x ^ y;
+ bcopy(buf + 12, &y, sizeof(y));
+ x = x ^ y;
+ return (x);
+}