summaryrefslogtreecommitdiffstats
path: root/hdlcutil/hdrvcomm.c
diff options
context:
space:
mode:
Diffstat (limited to 'hdlcutil/hdrvcomm.c')
-rw-r--r--hdlcutil/hdrvcomm.c146
1 files changed, 95 insertions, 51 deletions
diff --git a/hdlcutil/hdrvcomm.c b/hdlcutil/hdrvcomm.c
index 05259e5..2c7560e 100644
--- a/hdlcutil/hdrvcomm.c
+++ b/hdlcutil/hdrvcomm.c
@@ -3,7 +3,7 @@
/*
* hdrvcomm.c -- HDLC driver communications.
*
- * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch)
+ * Copyright (C) 1996-1998 Thomas Sailer (sailer@ife.ee.ethz.ch)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -25,7 +25,8 @@
*
*
* History:
- * 0.1 10.5.97 Started
+ * 0.1 10.05.97 Started
+ * 0.2 14.04.98 Tried to implement AF_PACKET
*/
/*****************************************************************************/
@@ -36,33 +37,34 @@
#include <errno.h>
#include <sys/ioctl.h>
#include <sys/types.h>
-#include <sys/socket.h>
+/*#include <sys/socket.h>*/
#include <sys/ipc.h>
#include <sys/msg.h>
#include <asm/byteorder.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
-#ifdef __GLIBC__
-#include <netinet/if_ether.h>
-#else
-#include <linux/if_ether.h>
-#endif
#include <net/if.h>
#include "hdrvcomm.h"
#include "usersmdiag.h"
+#include <net/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/if_packet.h>
+#ifndef SOL_PACKET
+#define SOL_PACKET 263
+#endif
-#include <linux/hdlcdrv.h>
/* ---------------------------------------------------------------------- */
#ifdef HDRVC_KERNEL
static int kernel_mode = 1;
#endif /* HDRVC_KERNEL */
-static char *if_name = "bc0";
+static char *if_name = "bcsf0";
static char *prg_name;
static int fd = -1;
static struct ifreq ifr_h;
static int promisc = 0;
+static int afpacket = 1;
static int msqid = -1;
/* ---------------------------------------------------------------------- */
@@ -93,39 +95,62 @@ static void terminate_sig(int signal)
int hdrvc_recvpacket(char *pkt, int maxlen)
{
struct ifreq ifr_new;
- struct sockaddr from;
+ struct sockaddr_ll from;
int from_len = sizeof(from);
#ifdef HDRVC_KERNEL
if (kernel_mode) {
if (!promisc) {
- struct sockaddr sa;
+ if (afpacket) {
+ struct sockaddr_ll sll;
+ struct packet_mreq mr;
+
+ memset(&sll, 0, sizeof(sll));
+ sll.sll_family = AF_PACKET;
+ sll.sll_ifindex = ifr_h.ifr_ifindex;
+ sll.sll_protocol = htons(ETH_P_AX25);
+ if (bind(fd, (struct sockaddr *)&sll, sizeof(sll)) < 0) {
+ fprintf(stderr, "%s: Error %s (%i) bind failed\n",
+ prg_name, strerror(errno), errno);
+ exit(-2);
+ }
+ memset(&mr, 0, sizeof(mr));
+ mr.mr_ifindex = sll.sll_ifindex;
+ mr.mr_type = PACKET_MR_PROMISC;
+ if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, (char *)&mr, sizeof(mr)) < 0) {
+ fprintf(stderr, "%s: Error %s (%i) setsockopt SOL_PACKET, PACKET_ADD_MEMBERSHIP failed\n",
+ prg_name, strerror(errno), errno);
+ exit(-2);
+ }
+ } else {
+ struct sockaddr sa;
- strcpy(sa.sa_data, if_name);
- sa.sa_family = AF_INET;
- if (bind(fd, &sa, sizeof(struct sockaddr)) < 0) {
- fprintf(stderr, "%s: Error %s (%i) bind failed\n",
- prg_name, strerror(errno), errno);
- exit(-2);
- }
- ifr_new = ifr_h;
- ifr_new.ifr_flags |= IFF_PROMISC;
- if (ioctl(fd, SIOCSIFFLAGS, &ifr_new) < 0) {
- perror("ioctl (SIOCSIFFLAGS)");
- exit(1);
- }
- signal(SIGTERM, terminate_sig);
- signal(SIGQUIT, terminate_sig);
- if (atexit((void (*)(void))terminate)) {
- perror("atexit");
- terminate();
+ strcpy(sa.sa_data, if_name);
+ sa.sa_family = AF_INET;
+ if (bind(fd, &sa, sizeof(sa)) < 0) {
+ fprintf(stderr, "%s: Error %s (%i) bind failed\n",
+ prg_name, strerror(errno), errno);
+ exit(-2);
+ }
+ ifr_new = ifr_h;
+ ifr_new.ifr_flags |= IFF_PROMISC;
+ if (ioctl(fd, SIOCSIFFLAGS, &ifr_new) < 0) {
+ perror("ioctl (SIOCSIFFLAGS)");
+ exit(1);
+ }
+ signal(SIGTERM, terminate_sig);
+ signal(SIGQUIT, terminate_sig);
+ if (atexit((void (*)(void))terminate)) {
+ perror("atexit");
+ terminate();
+ }
}
promisc = 1;
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
}
if (!pkt || maxlen < 2)
return 0;
- return recvfrom(fd, pkt, maxlen, 0, &from, &from_len);
+ return recvfrom(fd, pkt, maxlen, 0, (struct sockaddr *)&from, &from_len);
}
#endif /* HDRVC_KERNEL */
return -1;
@@ -185,34 +210,53 @@ void hdrvc_args(int *argc, char *argv[], char *def_if)
void hdrvc_init(void)
{
+ key_t k;
+ static struct ifreq ifr;
+
#ifdef HDRVC_KERNEL
if (kernel_mode) {
- if ((fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_AX25))) < 0) {
- fprintf(stderr, "%s: Error %s (%i), cannot open %s\n", prg_name,
- strerror(errno), errno, if_name);
- exit(-1);
- }
strcpy(ifr_h.ifr_name, if_name);
- if (ioctl(fd, SIOCGIFFLAGS, &ifr_h) < 0) {
- fprintf(stderr, "%s: Error %s (%i), cannot ioctl %s\n", prg_name,
- strerror(errno), errno, if_name);
- exit(-1);
+ /* first try to use AF_PACKET */
+ if ((fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_AX25))) < 0
+ || ioctl(fd, SIOCGIFINDEX, &ifr_h) < 0) {
+ if (fd >= 0)
+ close(fd);
+ afpacket = 0;
+ if ((fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_AX25))) < 0) {
+ fprintf(stderr, "%s: Error %s (%i), cannot open %s\n", prg_name,
+ strerror(errno), errno, if_name);
+ exit(-1);
+ }
+ if (ioctl(fd, SIOCGIFFLAGS, &ifr_h) < 0) {
+ fprintf(stderr, "%s: Error %s (%i), cannot ioctl SIOCGIFFLAGS %s\n", prg_name,
+ strerror(errno), errno, if_name);
+ exit(-1);
+ }
}
- } else
-#endif /* HDRVC_KERNEL */
- {
- key_t k = ftok(if_name, USERSM_KEY_PROJ);
-
- if (k == (key_t)-1) {
- fprintf(stderr, "%s: Error %s (%i), cannot ftok on %s\n", prg_name,
+ strcpy(ifr.ifr_name, if_name);
+ if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0 ) {
+ fprintf(stderr, "%s: Error %s (%i), cannot ioctl SIOCGIFHWADDR %s\n", prg_name,
strerror(errno), errno, if_name);
exit(-1);
- }
- if ((msqid = msgget(k, 0700)) < 0) {
- fprintf(stderr, "%s: Error %s (%i), cannot msgget %d\n", prg_name,
- strerror(errno), errno, k);
+ }
+ if (ifr.ifr_hwaddr.sa_family != ARPHRD_AX25) {
+ fprintf(stderr, "%s: Error, interface %s not AX25 (%i)\n", prg_name,
+ if_name, ifr.ifr_hwaddr.sa_family);
exit(-1);
}
+ return;
+ }
+#endif /* HDRVC_KERNEL */
+ k = ftok(if_name, USERSM_KEY_PROJ);
+ if (k == (key_t)-1) {
+ fprintf(stderr, "%s: Error %s (%i), cannot ftok on %s\n", prg_name,
+ strerror(errno), errno, if_name);
+ exit(-1);
+ }
+ if ((msqid = msgget(k, 0700)) < 0) {
+ fprintf(stderr, "%s: Error %s (%i), cannot msgget %d\n", prg_name,
+ strerror(errno), errno, k);
+ exit(-1);
}
}