File: [local] / src / usr.sbin / dvmrpd / kmroute.c (download)
Revision 1.3, Fri Jun 28 13:32:47 2019 UTC (4 years, 11 months ago) by deraadt
Branch: MAIN
CVS Tags: OPENBSD_7_5_BASE, OPENBSD_7_5, OPENBSD_7_4_BASE, OPENBSD_7_4, OPENBSD_7_3_BASE, OPENBSD_7_3, OPENBSD_7_2_BASE, OPENBSD_7_2, OPENBSD_7_1_BASE, OPENBSD_7_1, OPENBSD_7_0_BASE, OPENBSD_7_0, OPENBSD_6_9_BASE, OPENBSD_6_9, OPENBSD_6_8_BASE, OPENBSD_6_8, OPENBSD_6_7_BASE, OPENBSD_6_7, OPENBSD_6_6_BASE, OPENBSD_6_6, HEAD Changes since 1.2: +7 -7 lines
When system calls indicate an error they return -1, not some arbitrary
value < 0. errno is only updated in this case. Change all (most?)
callers of syscalls to follow this better, and let's see if this strictness
helps us in the future.
|
/* $OpenBSD: kmroute.c,v 1.3 2019/06/28 13:32:47 deraadt Exp $ */
/*
* Copyright (c) 2005, 2006 Esben Norby <norby@openbsd.org>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip_mroute.h>
#include <err.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include "igmp.h"
#include "dvmrpd.h"
#include "dvmrp.h"
#include "dvmrpe.h"
#include "log.h"
extern struct dvmrpd_conf *conf;
char *mroute_ptr; /* packet buffer */
void main_imsg_compose_rde(int, pid_t, void *, u_int16_t);
int
kmr_init(int fd)
{
struct iface *iface;
struct route_report rr;
LIST_FOREACH(iface, &conf->iface_list, entry) {
log_debug("kmr_init: interface %s", iface->name);
rr.net.s_addr = iface->addr.s_addr & iface->mask.s_addr;
rr.mask = iface->mask;
rr.nexthop.s_addr = 0;
rr.metric = iface->metric;
rr.ifindex = iface->ifindex;
main_imsg_compose_rde(IMSG_ROUTE_REPORT, -1, &rr, sizeof(rr));
mrt_add_vif(conf->mroute_socket, iface);
}
if ((mroute_ptr = calloc(1, IBUF_READ_SIZE)) == NULL)
fatal("kmr_init");
return (0);
}
void
kmr_shutdown(void)
{
struct iface *iface;
kmr_mfc_decouple();
kmroute_clear();
LIST_FOREACH(iface, &conf->iface_list, entry) {
log_debug("kmr_shutdown: interface %s", iface->name);
mrt_del_vif(conf->mroute_socket, iface);
}
free(mroute_ptr);
}
void
kmr_recv_msg(int fd, short event, void *bula)
{
struct mfc mfc;
struct igmpmsg kernel_msg;
char *buf;
ssize_t r;
if (event != EV_READ)
return;
/* setup buffer */
buf = mroute_ptr;
if ((r = recvfrom(fd, buf, IBUF_READ_SIZE, 0, NULL, NULL)) == -1) {
if (errno != EAGAIN && errno != EINTR)
log_debug("kmr_recv_msg: error receiving packet");
return;
}
memcpy(&kernel_msg, buf, sizeof(kernel_msg));
/* we are only interested in kernel messages */
if (kernel_msg.im_mbz != 0)
return;
switch (kernel_msg.im_msgtype) {
case IGMPMSG_NOCACHE:
/* verify that dst is a multicast group */
if (!IN_MULTICAST(ntohl(kernel_msg.im_dst.s_addr))) {
log_debug("kmr_recv_msg: kernel providing garbage!");
return;
}
/* send MFC entry to RDE */
mfc.origin = kernel_msg.im_src;
mfc.group = kernel_msg.im_dst;
mfc.ifindex = kernel_msg.im_vif;
main_imsg_compose_rde(IMSG_MFC_ADD, 0, &mfc, sizeof(mfc));
break;
case IGMPMSG_WRONGVIF:
case IGMPMSG_WHOLEPKT:
case IGMPMSG_BW_UPCALL:
default:
log_debug("kmr_recv_msg: unhandled msg type %d!",
kernel_msg.im_msgtype);
}
}
void
kmr_mfc_couple(void)
{
log_info("kernel multicast forwarding cache coupled");
}
void
kmr_mfc_decouple(void)
{
log_info("kernel multicast forwarding cache decoupled");
}
void
kmroute_clear(void)
{
}
int
mrt_init(int fd)
{
int flag = 1;
if (setsockopt(fd, IPPROTO_IP, MRT_INIT, &flag,
sizeof(flag)) == -1) {
log_warn("mrt_init: error setting MRT_INIT");
return (-1);
}
return (0);
}
int
mrt_done(int fd)
{
int flag = 0;
if (setsockopt(fd, IPPROTO_IP, MRT_DONE, &flag,
sizeof(flag)) == -1) {
log_warn("mrt_done: error setting MRT_DONE");
return (-1);
}
return (0);
}
int
mrt_add_vif(int fd, struct iface *iface)
{
struct vifctl vc;
vc.vifc_vifi = iface->ifindex;
vc.vifc_flags = 0;
vc.vifc_threshold = 1;
vc.vifc_rate_limit = 0;
vc.vifc_lcl_addr.s_addr = iface->addr.s_addr;
vc.vifc_rmt_addr.s_addr = 0;
if (setsockopt(fd, IPPROTO_IP, MRT_ADD_VIF, &vc,
sizeof(vc)) == -1) {
log_warn("mrt_add_vif: error adding VIF");
return (-1);
}
return (0);
}
void
mrt_del_vif(int fd, struct iface *iface)
{
vifi_t vifi;
vifi = iface->ifindex;
if (setsockopt(fd, IPPROTO_IP, MRT_DEL_VIF, &vifi,
sizeof(vifi)) == -1)
log_warn("mrt_del_vif: error deleting VIF");
}
int
mrt_add_mfc(int fd, struct mfc *mfc)
{
struct mfcctl mc;
int i;
log_debug("mrt_add_mfc: interface %d, group %s", mfc->ifindex,
inet_ntoa(mfc->group));
mc.mfcc_origin = mfc->origin;
mc.mfcc_mcastgrp = mfc->group;
mc.mfcc_parent = mfc->ifindex;
for (i = 0; i < MAXVIFS; i++) {
mc.mfcc_ttls[i] = mfc->ttls[i];
}
if (setsockopt(fd, IPPROTO_IP, MRT_ADD_MFC, &mc, sizeof(mc))
== -1) {
log_warnx("mrt_add_mfc: error adding group %s to interface %d",
inet_ntoa(mfc->group), mfc->ifindex);
return (-1);
}
return (0);
}
int
mrt_del_mfc(int fd, struct mfc *mfc)
{
struct mfcctl mc;
log_debug("mrt_del_mfc: group %s", inet_ntoa(mfc->group));
mc.mfcc_origin = mfc->origin;
mc.mfcc_mcastgrp = mfc->group;
if (setsockopt(fd, IPPROTO_IP, MRT_DEL_MFC, &mc, sizeof(mc))
== -1) {
log_warnx("mrt_del_mfc: error deleting group %s ",
inet_ntoa(mfc->group));
return (-1);
}
return (0);
}