summaryrefslogtreecommitdiffstats
path: root/usr.sbin/dhcrelay
diff options
context:
space:
mode:
authorrzalamena <rzalamena@openbsd.org>2016-12-08 19:18:15 +0000
committerrzalamena <rzalamena@openbsd.org>2016-12-08 19:18:15 +0000
commitfa3d4f89ea9f3cd6bef308c90703049bb4276c77 (patch)
tree97feced57967b50b11ad02acc9ba1b044c939f5d /usr.sbin/dhcrelay
parentFix mira's next intra-rate calculations for MCS >= 8. (diff)
downloadwireguard-openbsd-fa3d4f89ea9f3cd6bef308c90703049bb4276c77.tar.xz
wireguard-openbsd-fa3d4f89ea9f3cd6bef308c90703049bb4276c77.zip
Clean up function prototypes: use a single struct to hold all address
information instead of passing multiple different parameters. This also prepares the dhcrelay code to receive new features, like: IPv6, layer 2 relaying. ok jca@
Diffstat (limited to 'usr.sbin/dhcrelay')
-rw-r--r--usr.sbin/dhcrelay/bpf.c21
-rw-r--r--usr.sbin/dhcrelay/dhcpd.h41
-rw-r--r--usr.sbin/dhcrelay/dhcrelay.c46
-rw-r--r--usr.sbin/dhcrelay/dispatch.c23
-rw-r--r--usr.sbin/dhcrelay/packet.c58
5 files changed, 104 insertions, 85 deletions
diff --git a/usr.sbin/dhcrelay/bpf.c b/usr.sbin/dhcrelay/bpf.c
index d211b6f78cf..2b5e07fbbd2 100644
--- a/usr.sbin/dhcrelay/bpf.c
+++ b/usr.sbin/dhcrelay/bpf.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: bpf.c,v 1.12 2016/12/08 09:29:50 rzalamena Exp $ */
+/* $OpenBSD: bpf.c,v 1.13 2016/12/08 19:18:15 rzalamena Exp $ */
/* BPF socket interface code, originally contributed by Archie Cobbs. */
@@ -258,24 +258,23 @@ if_register_receive(struct interface_info *info)
ssize_t
send_packet(struct interface_info *interface,
- struct dhcp_packet *raw, size_t len, struct in_addr from,
- struct sockaddr_in *to, struct hardware *hto)
+ struct dhcp_packet *raw, size_t len, struct packet_ctx *pc)
{
unsigned char buf[256];
struct iovec iov[2];
int result, bufp = 0;
if (interface->hw_address.htype == HTYPE_IPSEC_TUNNEL) {
- socklen_t slen = sizeof(*to);
+ socklen_t slen = pc->pc_dst.ss_len;
result = sendto(server_fd, raw, len, 0,
- (struct sockaddr *)to, slen);
+ (struct sockaddr *)&pc->pc_dst, slen);
goto done;
}
/* Assemble the headers... */
- assemble_hw_header(interface, buf, &bufp, hto);
- assemble_udp_ip_header(interface, buf, &bufp, from.s_addr,
- to->sin_addr.s_addr, to->sin_port, (unsigned char *)raw, len);
+ assemble_hw_header(interface, buf, &bufp, pc);
+ assemble_udp_ip_header(interface, buf, &bufp, pc,
+ (unsigned char *)raw, len);
/* Fire it off */
iov[0].iov_base = (char *)buf;
@@ -292,7 +291,7 @@ send_packet(struct interface_info *interface,
ssize_t
receive_packet(struct interface_info *interface, unsigned char *buf,
- size_t len, struct sockaddr_in *from, struct hardware *hfrom)
+ size_t len, struct packet_ctx *pc)
{
int length = 0, offset = 0;
struct bpf_hdr hdr;
@@ -358,7 +357,7 @@ receive_packet(struct interface_info *interface, unsigned char *buf,
/* Decode the physical header... */
offset = decode_hw_header(interface,
- interface->rbuf, interface->rbuf_offset, hfrom);
+ interface->rbuf, interface->rbuf_offset, pc);
/*
* If a physical layer checksum failed (dunno of any
@@ -374,7 +373,7 @@ receive_packet(struct interface_info *interface, unsigned char *buf,
/* Decode the IP and UDP headers... */
offset = decode_udp_ip_header(interface, interface->rbuf,
- interface->rbuf_offset, from, hdr.bh_caplen);
+ interface->rbuf_offset, pc, hdr.bh_caplen);
/* If the IP or UDP checksum was bad, skip the packet... */
if (offset < 0) {
diff --git a/usr.sbin/dhcrelay/dhcpd.h b/usr.sbin/dhcrelay/dhcpd.h
index 6c922a40988..48067e2c8ec 100644
--- a/usr.sbin/dhcrelay/dhcpd.h
+++ b/usr.sbin/dhcrelay/dhcpd.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcpd.h,v 1.16 2016/12/08 09:29:50 rzalamena Exp $ */
+/* $OpenBSD: dhcpd.h,v 1.17 2016/12/08 19:18:15 rzalamena Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@openbsd.org>
@@ -42,15 +42,28 @@
#define SERVER_PORT 67
#define CLIENT_PORT 68
+/* Maximum size of client hardware address. */
+#define CHADDR_SIZE 16
+
+struct packet_ctx {
+ uint8_t pc_htype;
+ uint8_t pc_hlen;
+ uint8_t pc_smac[CHADDR_SIZE];
+ uint8_t pc_dmac[CHADDR_SIZE];
+
+ struct sockaddr_storage pc_src;
+ struct sockaddr_storage pc_dst;
+};
+
struct iaddr {
int len;
- unsigned char iabuf[16];
+ unsigned char iabuf[CHADDR_SIZE];
};
struct hardware {
u_int8_t htype;
u_int8_t hlen;
- u_int8_t haddr[16];
+ u_int8_t haddr[CHADDR_SIZE];
};
/* Possible states in which the client can be. */
@@ -112,15 +125,13 @@ int if_register_bpf(struct interface_info *);
void if_register_send(struct interface_info *);
void if_register_receive(struct interface_info *);
ssize_t send_packet(struct interface_info *,
- struct dhcp_packet *, size_t, struct in_addr,
- struct sockaddr_in *, struct hardware *);
+ struct dhcp_packet *, size_t, struct packet_ctx *);
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t,
- struct sockaddr_in *, struct hardware *);
+ struct packet_ctx *);
/* dispatch.c */
extern void (*bootp_packet_handler)(struct interface_info *,
- struct dhcp_packet *, int, unsigned int, struct iaddr,
- struct hardware *);
+ struct dhcp_packet *, int, struct packet_ctx *);
struct interface_info *get_interface(const char *,
void (*)(struct protocol *));
void dispatch(void);
@@ -130,13 +141,13 @@ void remove_protocol(struct protocol *);
/* packet.c */
void assemble_hw_header(struct interface_info *, unsigned char *,
- int *, struct hardware *);
+ int *, struct packet_ctx *);
void assemble_udp_ip_header(struct interface_info *, unsigned char *,
- int *, u_int32_t, u_int32_t, unsigned int, unsigned char *, int);
+ int *, struct packet_ctx *pc, unsigned char *, int);
ssize_t decode_hw_header(struct interface_info *, unsigned char *,
- int, struct hardware *);
+ int, struct packet_ctx *);
ssize_t decode_udp_ip_header(struct interface_info *, unsigned char *,
- int, struct sockaddr_in *, int);
+ int, struct packet_ctx *, int);
/* dhcrelay.c */
extern u_int16_t server_port;
@@ -147,3 +158,9 @@ extern int server_fd;
extern time_t cur_time;
extern int log_priority;
extern int log_perror;
+
+static inline struct sockaddr_in *
+ss2sin(struct sockaddr_storage *ss)
+{
+ return ((struct sockaddr_in *)ss);
+}
diff --git a/usr.sbin/dhcrelay/dhcrelay.c b/usr.sbin/dhcrelay/dhcrelay.c
index dfb31846947..75664b3c04f 100644
--- a/usr.sbin/dhcrelay/dhcrelay.c
+++ b/usr.sbin/dhcrelay/dhcrelay.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dhcrelay.c,v 1.48 2016/12/08 09:29:50 rzalamena Exp $ */
+/* $OpenBSD: dhcrelay.c,v 1.49 2016/12/08 19:18:15 rzalamena Exp $ */
/*
* Copyright (c) 2004 Henning Brauer <henning@cvs.openbsd.org>
@@ -65,7 +65,7 @@
void usage(void);
int rdaemon(int);
void relay(struct interface_info *, struct dhcp_packet *, int,
- unsigned int, struct iaddr, struct hardware *);
+ struct packet_ctx *);
char *print_hw_addr(int, int, unsigned char *);
void got_response(struct protocol *);
int get_rdomain(char *);
@@ -264,11 +264,10 @@ main(int argc, char *argv[])
void
relay(struct interface_info *ip, struct dhcp_packet *packet, int length,
- unsigned int from_port, struct iaddr from, struct hardware *hfrom)
+ struct packet_ctx *pc)
{
struct server_list *sp;
struct sockaddr_in to;
- struct hardware hto;
if (packet->hlen > sizeof packet->chaddr) {
note("Discarding packet with invalid hlen.");
@@ -287,6 +286,7 @@ relay(struct interface_info *ip, struct dhcp_packet *packet, int length,
}
to.sin_family = AF_INET;
to.sin_len = sizeof to;
+ *ss2sin(&pc->pc_dst) = to;
/*
* Set up the hardware destination address. If it's a reply
@@ -294,13 +294,13 @@ relay(struct interface_info *ip, struct dhcp_packet *packet, int length,
* cast as well.
*/
if (!(packet->flags & htons(BOOTP_BROADCAST))) {
- hto.hlen = packet->hlen;
- if (hto.hlen > sizeof hto.haddr)
- hto.hlen = sizeof hto.haddr;
- memcpy(hto.haddr, packet->chaddr, hto.hlen);
- hto.htype = packet->htype;
+ pc->pc_hlen = packet->hlen;
+ if (pc->pc_hlen > CHADDR_SIZE)
+ pc->pc_hlen = CHADDR_SIZE;
+ memcpy(pc->pc_dmac, packet->chaddr, pc->pc_hlen);
+ pc->pc_htype = packet->htype;
} else {
- bzero(&hto, sizeof(hto));
+ memset(pc->pc_dmac, 0xff, sizeof(pc->pc_dmac));
}
if ((length = relay_agentinfo(interfaces,
@@ -321,8 +321,8 @@ relay(struct interface_info *ip, struct dhcp_packet *packet, int length,
*/
packet->giaddr.s_addr = 0x0;
- if (send_packet(interfaces, packet, length,
- interfaces->primary_address, &to, &hto) != -1)
+ ss2sin(&pc->pc_src)->sin_addr = interfaces->primary_address;
+ if (send_packet(interfaces, packet, length, pc) != -1)
debug("forwarded BOOTREPLY for %s to %s",
print_hw_addr(packet->htype, packet->hlen,
packet->chaddr), inet_ntoa(to.sin_addr));
@@ -351,7 +351,7 @@ relay(struct interface_info *ip, struct dhcp_packet *packet, int length,
packet->giaddr = ip->primary_address;
if ((length = relay_agentinfo(ip, packet, length,
- (struct in_addr *)from.iabuf, NULL)) == -1) {
+ &ss2sin(&pc->pc_src)->sin_addr, NULL)) == -1) {
note("ignoring BOOTREQUEST with invalid "
"relay agent information");
return;
@@ -439,8 +439,8 @@ bad:
void
got_response(struct protocol *l)
{
+ struct packet_ctx pc;
ssize_t result;
- struct iaddr ifrom;
union {
/*
* Packet input buffer. Must be as large as largest
@@ -473,13 +473,19 @@ got_response(struct protocol *l)
return;
}
- if (bootp_packet_handler) {
- ifrom.len = 4;
- memcpy(ifrom.iabuf, &sp->to.sin_addr, ifrom.len);
+ memset(&pc, 0, sizeof(pc));
+ pc.pc_src.ss_family = AF_INET;
+ pc.pc_src.ss_len = sizeof(struct sockaddr_in);
+ memcpy(&ss2sin(&pc.pc_src)->sin_addr, &sp->to.sin_addr,
+ sizeof(ss2sin(&pc.pc_src)->sin_addr));
+ ss2sin(&pc.pc_src)->sin_port = server_port;
- (*bootp_packet_handler)(NULL, &u.packet, result,
- sp->to.sin_port, ifrom, NULL);
- }
+ pc.pc_dst.ss_family = AF_INET;
+ pc.pc_dst.ss_len = sizeof(struct sockaddr_in);
+ ss2sin(&pc.pc_dst)->sin_port = client_port;
+
+ if (bootp_packet_handler)
+ (*bootp_packet_handler)(NULL, &u.packet, result, &pc);
}
ssize_t
diff --git a/usr.sbin/dhcrelay/dispatch.c b/usr.sbin/dhcrelay/dispatch.c
index 649a7e29200..d212969158d 100644
--- a/usr.sbin/dhcrelay/dispatch.c
+++ b/usr.sbin/dhcrelay/dispatch.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dispatch.c,v 1.13 2016/12/08 09:29:50 rzalamena Exp $ */
+/* $OpenBSD: dispatch.c,v 1.14 2016/12/08 19:18:15 rzalamena Exp $ */
/*
* Copyright 2004 Henning Brauer <henning@openbsd.org>
@@ -69,8 +69,7 @@ static struct timeout *free_timeouts;
static int interfaces_invalidated;
void (*bootp_packet_handler)(struct interface_info *,
- struct dhcp_packet *, int, unsigned int,
- struct iaddr, struct hardware *);
+ struct dhcp_packet *, int, struct packet_ctx *);
static int interface_status(struct interface_info *ifinfo);
@@ -260,9 +259,7 @@ another:
void
got_one(struct protocol *l)
{
- struct sockaddr_in from;
- struct hardware hfrom;
- struct iaddr ifrom;
+ struct packet_ctx pc;
size_t result;
union {
/*
@@ -274,8 +271,9 @@ got_one(struct protocol *l)
} u;
struct interface_info *ip = l->local;
- if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
- &hfrom)) == -1) {
+ memset(&pc, 0, sizeof(pc));
+
+ if ((result = receive_packet(ip, u.packbuf, sizeof(u), &pc)) == -1) {
warning("receive_packet failed on %s: %s", ip->name,
strerror(errno));
ip->errors++;
@@ -295,13 +293,8 @@ got_one(struct protocol *l)
if (result == 0)
return;
- if (bootp_packet_handler) {
- ifrom.len = 4;
- memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
-
- (*bootp_packet_handler)(ip, &u.packet, result,
- from.sin_port, ifrom, &hfrom);
- }
+ if (bootp_packet_handler)
+ (*bootp_packet_handler)(ip, &u.packet, result, &pc);
}
int
diff --git a/usr.sbin/dhcrelay/packet.c b/usr.sbin/dhcrelay/packet.c
index bdca40a8e45..547ce33c980 100644
--- a/usr.sbin/dhcrelay/packet.c
+++ b/usr.sbin/dhcrelay/packet.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: packet.c,v 1.11 2016/02/07 00:49:28 krw Exp $ */
+/* $OpenBSD: packet.c,v 1.12 2016/12/08 19:18:15 rzalamena Exp $ */
/* Packet assembly code, originally contributed by Archie Cobbs. */
@@ -97,17 +97,13 @@ wrapsum(u_int32_t sum)
void
assemble_hw_header(struct interface_info *interface, unsigned char *buf,
- int *bufix, struct hardware *to)
+ int *bufix, struct packet_ctx *pc)
{
struct ether_header eh;
- if (to != NULL && to->hlen == 6) /* XXX */
- memcpy(eh.ether_dhost, to->haddr, sizeof(eh.ether_dhost));
- else
- memset(eh.ether_dhost, 0xff, sizeof(eh.ether_dhost));
-
- /* source address is filled in by the kernel */
- memset(eh.ether_shost, 0x00, sizeof(eh.ether_shost));
+ /* Use the supplied address or let the kernel fill it. */
+ memcpy(eh.ether_shost, pc->pc_smac, ETHER_ADDR_LEN);
+ memcpy(eh.ether_dhost, pc->pc_dmac, ETHER_ADDR_LEN);
eh.ether_type = htons(ETHERTYPE_IP);
@@ -117,8 +113,7 @@ assemble_hw_header(struct interface_info *interface, unsigned char *buf,
void
assemble_udp_ip_header(struct interface_info *interface, unsigned char *buf,
- int *bufix, u_int32_t from, u_int32_t to, unsigned int port,
- unsigned char *data, int len)
+ int *bufix, struct packet_ctx *pc, unsigned char *data, int len)
{
struct ip ip;
struct udphdr udp;
@@ -132,15 +127,15 @@ assemble_udp_ip_header(struct interface_info *interface, unsigned char *buf,
ip.ip_ttl = 16;
ip.ip_p = IPPROTO_UDP;
ip.ip_sum = 0;
- ip.ip_src.s_addr = from;
- ip.ip_dst.s_addr = to;
+ ip.ip_src.s_addr = ss2sin(&pc->pc_src)->sin_addr.s_addr;
+ ip.ip_dst.s_addr = ss2sin(&pc->pc_dst)->sin_addr.s_addr;
ip.ip_sum = wrapsum(checksum((unsigned char *)&ip, sizeof(ip), 0));
memcpy(&buf[*bufix], &ip, sizeof(ip));
*bufix += sizeof(ip);
- udp.uh_sport = server_port; /* XXX */
- udp.uh_dport = port; /* XXX */
+ udp.uh_sport = ss2sin(&pc->pc_src)->sin_port;
+ udp.uh_dport = ss2sin(&pc->pc_dst)->sin_port;
udp.uh_ulen = htons(sizeof(udp) + len);
memset(&udp.uh_sum, 0, sizeof(udp.uh_sum));
@@ -155,9 +150,8 @@ assemble_udp_ip_header(struct interface_info *interface, unsigned char *buf,
ssize_t
decode_hw_header(struct interface_info *interface, unsigned char *buf,
- int bufix, struct hardware *from)
+ int bufix, struct packet_ctx *pc)
{
- struct ether_header eh;
size_t offset = 0;
if (interface->hw_address.htype == HTYPE_IPSEC_TUNNEL) {
@@ -172,23 +166,24 @@ decode_hw_header(struct interface_info *interface, unsigned char *buf,
if (ip->ip_p != IPPROTO_IPIP)
return (-1);
- bzero(&eh, sizeof(eh));
+ memset(pc->pc_dmac, 0xff, ETHER_ADDR_LEN);
offset = ENC_HDRLEN + ip_len;
- } else {
- memcpy(&eh, buf + bufix, ETHER_HDR_LEN);
- offset = sizeof(eh);
+ } else {
+ memcpy(pc->pc_dmac, buf + bufix, ETHER_ADDR_LEN);
+ memcpy(pc->pc_smac, buf + bufix + ETHER_ADDR_LEN,
+ ETHER_ADDR_LEN);
+ offset = sizeof(struct ether_header);
}
- memcpy(from->haddr, eh.ether_shost, sizeof(eh.ether_shost));
- from->htype = ARPHRD_ETHER;
- from->hlen = sizeof(eh.ether_shost);
+ pc->pc_htype = ARPHRD_ETHER;
+ pc->pc_hlen = ETHER_ADDR_LEN;
return (offset);
}
ssize_t
decode_udp_ip_header(struct interface_info *interface, unsigned char *buf,
- int bufix, struct sockaddr_in *from, int buflen)
+ int bufix, struct packet_ctx *pc, int buflen)
{
struct ip *ip;
struct udphdr *udp;
@@ -224,7 +219,15 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf,
return (-1);
}
- memcpy(&from->sin_addr, &ip->ip_src, sizeof(from->sin_addr));
+ pc->pc_src.ss_len = sizeof(struct sockaddr_in);
+ pc->pc_src.ss_family = AF_INET;
+ memcpy(&ss2sin(&pc->pc_src)->sin_addr, &ip->ip_src,
+ sizeof(ss2sin(&pc->pc_src)->sin_addr));
+
+ pc->pc_dst.ss_len = sizeof(struct sockaddr_in);
+ pc->pc_dst.ss_family = AF_INET;
+ memcpy(&ss2sin(&pc->pc_dst)->sin_addr, &ip->ip_dst,
+ sizeof(ss2sin(&pc->pc_dst)->sin_addr));
#ifdef DEBUG
if (ntohs(ip->ip_len) != buflen)
@@ -291,7 +294,8 @@ decode_udp_ip_header(struct interface_info *interface, unsigned char *buf,
return (-1);
}
- memcpy(&from->sin_port, &udp->uh_sport, sizeof(udp->uh_sport));
+ ss2sin(&pc->pc_src)->sin_port = udp->uh_sport;
+ ss2sin(&pc->pc_dst)->sin_port = udp->uh_dport;
return (ip_len + sizeof(*udp));
}