Ejemplo n.º 1
0
static int
rtpp_stream_guess_addr(struct rtpp_stream *self,
  struct rtp_packet *packet)
{
    int rport;
    const char *actor, *ptype;
    struct rtpp_stream_priv *pvt;

    pvt = PUB2PVT(self);

    if (self->addr != NULL && ishostseq(self->addr, sstosa(&packet->raddr))) {
        return (0);
    }
    if (self->addr == NULL) {
        self->addr = malloc(packet->rlen);
        if (self->addr == NULL) {
            return (-1);
        }
    }
    actor = rtpp_stream_get_actor(self);
    ptype =  rtpp_stream_get_proto(self);
    rport = ntohs(satosin(&packet->raddr)->sin_port);
    if (IS_LAST_PORT(rport)) {
        return (-1);
    }
    memcpy(self->addr, &packet->raddr, packet->rlen);
    satosin(self->addr)->sin_port = htons(rport + 1);
    /* Use guessed value as the only true one for asymmetric clients */
    self->latch_info.latched = self->asymmetric;
    RTPP_LOG(pvt->pub.log, RTPP_LOG_INFO, "guessing %s port "
      "for %s to be %d", ptype, actor, rport + 1);

    return (0);
}
Ejemplo n.º 2
0
static int
prepare_pkt_hdr_adhoc(struct rtpp_session *sp, struct rtp_packet *packet,
  struct pkt_hdr_adhoc *hdrp, struct sockaddr *daddr, struct sockaddr *ldaddr,
  int ldport, int face)
{

    memset(hdrp, 0, sizeof(*hdrp));
    hdrp->time = packet->rtime;
    if (hdrp->time == -1) {
	rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "can't get current time");
	return -1;
    }
    switch (sstosa(&packet->raddr)->sa_family) {
    case AF_INET:
	hdrp->addr.in4.sin_family = sstosa(&packet->raddr)->sa_family;
	hdrp->addr.in4.sin_port = satosin(&packet->raddr)->sin_port;
	hdrp->addr.in4.sin_addr = satosin(&packet->raddr)->sin_addr;
	break;

    case AF_INET6:
	hdrp->addr.in6.sin_family = sstosa(&packet->raddr)->sa_family;
	hdrp->addr.in6.sin_port = satosin6(&packet->raddr)->sin6_port;
	hdrp->addr.in6.sin_addr = satosin6(&packet->raddr)->sin6_addr;
	break;

    default:
	abort();
    }

    hdrp->plen = packet->size;
    return 0;
}
Ejemplo n.º 3
0
/*
 * Start output on the mpe interface.
 */
void
mpestart(struct ifnet *ifp)
{
	struct mbuf 		*m;
	struct sockaddr		*sa = (struct sockaddr *)&mpedst;
	int			 s;
	sa_family_t		 af;
	struct rtentry		*rt;

	for (;;) {
		s = splnet();
		IFQ_DEQUEUE(&ifp->if_snd, m);
		splx(s);

		if (m == NULL)
			return;

		af = *mtod(m, sa_family_t *);
		m_adj(m, sizeof(af));
		switch (af) {
		case AF_INET:
			bzero(sa, sizeof(struct sockaddr_in));
			satosin(sa)->sin_family = af;
			satosin(sa)->sin_len = sizeof(struct sockaddr_in);
			bcopy(mtod(m, caddr_t), &satosin(sa)->sin_addr,
			    sizeof(in_addr_t));
			m_adj(m, sizeof(in_addr_t));
			break;
		default:
			m_freem(m);
			continue;
		}

		rt = rtalloc1(sa, RT_REPORT, 0);
		if (rt == NULL) {
			/* no route give up */
			m_freem(m);
			continue;
		}

#if NBPFILTER > 0
		if (ifp->if_bpf) {
			/* remove MPLS label before passing packet to bpf */
			m->m_data += sizeof(struct shim_hdr);
			m->m_len -= sizeof(struct shim_hdr);
			m->m_pkthdr.len -= sizeof(struct shim_hdr);
			bpf_mtap_af(ifp->if_bpf, af, m, BPF_DIRECTION_OUT);
			m->m_data -= sizeof(struct shim_hdr);
			m->m_len += sizeof(struct shim_hdr);
			m->m_pkthdr.len += sizeof(struct shim_hdr);
		}
#endif
		/* XXX lie, but mpls_output will only look at sa_family */
		sa->sa_family = AF_MPLS;

		mpls_output(rt->rt_ifp, m, sa, rt);
		RTFREE(rt);
	}
}
Ejemplo n.º 4
0
void
rwrite(struct rtpp_session *sp, void *rrc, struct sockaddr *saddr, void *buf, int len)
{
    struct iovec v[2];
    struct pkt_hdr hdr;
    int rval;

    if (RRC_CAST(rrc)->fd == -1)
        return;

    memset(&hdr, 0, sizeof(hdr));

    hdr.time = getctime();
    if (hdr.time == -1) {
	rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "can't get current time");
	goto fatal_error;
    }

    switch (saddr->sa_family) {
    case AF_INET:
	hdr.addr.in4.sin_family = saddr->sa_family;
	hdr.addr.in4.sin_port = satosin(saddr)->sin_port;
	hdr.addr.in4.sin_addr = satosin(saddr)->sin_addr;
	break;

    case AF_INET6:
	hdr.addr.in6.sin_family = saddr->sa_family;
	hdr.addr.in6.sin_port = satosin6(saddr)->sin6_port;
	hdr.addr.in6.sin_addr = satosin6(saddr)->sin6_addr;
	break;

    default:
	abort();
    }

    hdr.plen = len;

    v[0].iov_base = (void *)&hdr;
    v[0].iov_len = sizeof(hdr);
    v[1].iov_base = buf;
    v[1].iov_len = len;

    rval = writev(RRC_CAST(rrc)->fd, v, 2);
    if (rval != -1)
	return;

    rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "error while recording session (%s)",
      (sp->rtcp != NULL) ? "RTP" : "RTCP");
fatal_error:
    /* Prevent futher writing if error happens */
    close(RRC_CAST(rrc)->fd);
    RRC_CAST(rrc)->fd = -1;
}
Ejemplo n.º 5
0
int
server_lookup(struct sockaddr *client, struct sockaddr *proxy,
    struct sockaddr *server, u_int8_t proto)
{
	if (client->sa_family == AF_INET)
		return (server_lookup4(satosin(client), satosin(proxy),
		    satosin(server), proto));

	if (client->sa_family == AF_INET6)
		return (server_lookup6(satosin6(client), satosin6(proxy),
		    satosin6(server), proto));

	errno = EPROTONOSUPPORT;
	return (-1);
}
Ejemplo n.º 6
0
/*
 * Call at splnet().
 */
static void
tuninit(struct tun_softc *tp)
{
	struct ifnet	*ifp = &tp->tun_if;
	struct ifaddr	*ifa;

	TUNDEBUG("%s: tuninit\n", ifp->if_xname);

	mutex_enter(&tp->tun_lock);
	ifp->if_flags |= IFF_UP | IFF_RUNNING;

	tp->tun_flags &= ~(TUN_IASET|TUN_DSTADDR);
	IFADDR_FOREACH(ifa, ifp) {
#ifdef INET
		if (ifa->ifa_addr->sa_family == AF_INET) {
			struct sockaddr_in *sin;

			sin = satosin(ifa->ifa_addr);
			if (sin && sin->sin_addr.s_addr)
				tp->tun_flags |= TUN_IASET;

			if (ifp->if_flags & IFF_POINTOPOINT) {
				sin = satosin(ifa->ifa_dstaddr);
				if (sin && sin->sin_addr.s_addr)
					tp->tun_flags |= TUN_DSTADDR;
			}
		}
#endif
#ifdef INET6
		if (ifa->ifa_addr->sa_family == AF_INET6) {
			struct sockaddr_in6 *sin;

			sin = (struct sockaddr_in6 *)ifa->ifa_addr;
			if (!IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
				tp->tun_flags |= TUN_IASET;

			if (ifp->if_flags & IFF_POINTOPOINT) {
				sin = (struct sockaddr_in6 *)ifa->ifa_dstaddr;
				if (sin &&
				    !IN6_IS_ADDR_UNSPECIFIED(&sin->sin6_addr))
					tp->tun_flags |= TUN_DSTADDR;
			} else
				tp->tun_flags &= ~TUN_DSTADDR;
		}
#endif /* INET6 */
	}
	mutex_exit(&tp->tun_lock);
}
Ejemplo n.º 7
0
int
add_nat(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
    u_int16_t d_port, struct sockaddr *nat, u_int16_t nat_range_low,
    u_int16_t nat_range_high, u_int8_t proto)
{
	if (!src || !dst || !d_port || !nat || !nat_range_low || !proto ||
	    (src->sa_family != nat->sa_family)) {
		errno = EINVAL;
		return (-1);
	}

	if (prepare_rule(id, PF_RULESET_NAT, src, dst, d_port, proto) == -1)
		return (-1);

	if (nat->sa_family == AF_INET) {
		memcpy(&pfp.addr.addr.v.a.addr.v4,
		    &satosin(nat)->sin_addr.s_addr, 4);
		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4);
	} else {
		memcpy(&pfp.addr.addr.v.a.addr.v6,
		    &satosin6(nat)->sin6_addr.s6_addr, 16);
		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
	}
	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
		return (-1);

	pfr.rule.rpool.proxy_port[0] = nat_range_low;
	pfr.rule.rpool.proxy_port[1] = nat_range_high;
	if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
		return (-1);

	return (0);
}
Ejemplo n.º 8
0
char *
routename(struct sockaddr *sa, int flags)
{
	static char line[NI_MAXHOST];
	int error, f;

	f = (flags) ? NI_NUMERICHOST : 0;
	error = getnameinfo(sa, sa->sa_len, line, sizeof(line),
	    NULL, 0, f);
	if (error) {
		const void *src;
		switch (sa->sa_family) {
#ifdef INET
		case AF_INET:
			src = &satosin(sa)->sin_addr;
			break;
#endif /* INET */
#ifdef INET6
		case AF_INET6:
			src = &satosin6(sa)->sin6_addr;
			break;
#endif /* INET6 */
		default:
			return(line);
		}
		inet_ntop(sa->sa_family, src, line, sizeof(line) - 1);
		return (line);
	}
	trimdomain(line, strlen(line));

	return (line);
}
Ejemplo n.º 9
0
int
add_rdr(u_int32_t id, struct sockaddr *src, struct sockaddr *dst,
    u_int16_t d_port, struct sockaddr *rdr, u_int16_t rdr_port, u_int8_t proto)
{
	if (!src || !dst || !d_port || !rdr || !rdr_port || !proto ||
	    (src->sa_family != rdr->sa_family)) {
		errno = EINVAL;
		return (-1);
	}

	if (prepare_rule(id, PF_RULESET_RDR, src, dst, d_port, proto) == -1)
		return (-1);

	if (rdr->sa_family == AF_INET) {
		memcpy(&pfp.addr.addr.v.a.addr.v4,
		    &satosin(rdr)->sin_addr.s_addr, 4);
		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 4);
	} else {
		memcpy(&pfp.addr.addr.v.a.addr.v6,
		    &satosin6(rdr)->sin6_addr.s6_addr, 16);
		memset(&pfp.addr.addr.v.a.mask.addr8, 255, 16);
	}
	if (ioctl(dev, DIOCADDADDR, &pfp) == -1)
		return (-1);

	pfr.rule.rpool.proxy_port[0] = rdr_port;
	if (ioctl(dev, DIOCADDRULE, &pfr) == -1)
		return (-1);

	return (0);
}
Ejemplo n.º 10
0
int
mpeoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
	struct rtentry *rt)
{
	struct shim_hdr	shim;
	int		s;
	int		error;
	int		off;
	u_int8_t	op = 0;

#ifdef DIAGNOSTIC
	if (ifp->if_rdomain != rtable_l2(m->m_pkthdr.rdomain)) {
		printf("%s: trying to send packet on wrong domain. "
		    "if %d vs. mbuf %d\n", ifp->if_xname,
		    ifp->if_rdomain, rtable_l2(m->m_pkthdr.rdomain));
	}
#endif
	m->m_pkthdr.rcvif = ifp;
	/* XXX assumes MPLS is always in rdomain 0 */
	m->m_pkthdr.rdomain = 0;

	error = 0;
	switch (dst->sa_family) {
#ifdef INET
	case AF_INET:
		if (rt && rt->rt_flags & RTF_MPLS) {
			shim.shim_label =
			    ((struct rt_mpls *)rt->rt_llinfo)->mpls_label;
			shim.shim_label |= MPLS_BOS_MASK;
			op =  ((struct rt_mpls *)rt->rt_llinfo)->mpls_operation;
		}
		if (op != MPLS_OP_PUSH) {
			m_freem(m);
			error = ENETUNREACH;
			goto out;
		}
		if (mpls_mapttl_ip) {
			struct ip	*ip;
			ip = mtod(m, struct ip *);
			shim.shim_label |= htonl(ip->ip_ttl) & MPLS_TTL_MASK;
		} else
			shim.shim_label |= htonl(mpls_defttl) & MPLS_TTL_MASK;
		off = sizeof(sa_family_t) + sizeof(in_addr_t);
		M_PREPEND(m, sizeof(shim) + off, M_DONTWAIT);
		if (m == NULL) {
			error = ENOBUFS;
			goto out;
		}
		*mtod(m, sa_family_t *) = AF_INET;
		m_copyback(m, sizeof(sa_family_t), sizeof(in_addr_t),
		    (caddr_t)&((satosin(dst)->sin_addr)), M_NOWAIT);
		break;
#endif
	default:
		m_freem(m);
		error = EPFNOSUPPORT;
		goto out;
	}
Ejemplo n.º 11
0
Archivo: syslog.c Proyecto: boateam/boa
void
openlog(const char *ident, int logstat, int logfac)
{
	if (ident != NULL)
		LogTag = ident;
	LogStat = logstat;
	if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
		LogFacility = logfac;

	if (LogFile == -1) {
#ifndef USE_INET
		SyslogAddr.sa_family = AF_UNIX;
		(void)strncpy(SyslogAddr.sa_data, _PATH_LOG,
		    sizeof(SyslogAddr.sa_data));
		if (LogStat & LOG_NDELAY) {
			if ((LogFile = socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
				return;
			(void)fcntl(LogFile, F_SETFD, 1);
		}
#else
#define satosin(sa)     ((struct sockaddr_in *)(sa))

		satosin(&SyslogAddr)->sin_family = AF_INET;
		satosin(&SyslogAddr)->sin_port = 514;
		satosin(&SyslogAddr)->sin_addr.s_addr = inet_addr("127.0.0.1");
		if (LogStat & LOG_NDELAY) {
			if ((LogFile = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
				return;
			(void)fcntl(LogFile, F_SETFD, 1);
			if (connect(LogFile, &SyslogAddr,
			    sizeof(SyslogAddr)) < 0) {
				closelog();
				return;
			}
		}
#endif
	}
	if (LogFile != -1 && !connected) {
		if (connect(LogFile, &SyslogAddr, sizeof(SyslogAddr)) == -1) {
			(void)close(LogFile);
			LogFile = -1;
		} else
			connected = 1;
	}
}
Ejemplo n.º 12
0
int set_mcast_if(struct sockaddr *int_addr)
{
struct in_addr if_addr;
	if_addr.s_addr = satosin(*int_addr)->sin_addr.s_addr;
	return setsockopt_multicast_ipv4(sock, 
			IP_MULTICAST_IF, 
			if_addr,
			0xE0000009,
			0);
}
Ejemplo n.º 13
0
int mcast_leave(struct sockaddr *int_addr)
{
struct in_addr if_addr;
	if_addr.s_addr = satosin(*int_addr)->sin_addr.s_addr;
	return setsockopt_multicast_ipv4(sock, 
			IP_DROP_MEMBERSHIP, 
			if_addr,
			0xE0000009,
			0);
}
Ejemplo n.º 14
0
int
Mod_fw_lookup_orig_dst(FW_handle_T handle, struct sockaddr *src,
                       struct sockaddr *proxy, struct sockaddr *orig_dst)
{
    struct fw_handle *fwh = handle->fwh;

    if(src->sa_family == AF_INET) {
        return server_lookup4(fwh->pfdev, satosin(src), satosin(proxy),
                              satosin(orig_dst));
    }

    if(src->sa_family == AF_INET6) {
        return server_lookup6(fwh->pfdev, satosin6(src), satosin6(proxy),
                              satosin6(orig_dst));
    }

    errno = EPROTONOSUPPORT;
    return -1;
}
Ejemplo n.º 15
0
static int
create_twinlistener(struct cfg_stable *cf, struct sockaddr *ia, int port, int *fds)
{
    struct sockaddr_storage iac;
    int rval, i, flags;

    fds[0] = fds[1] = -1;

    rval = -1;

    for (i = 0; i < 2; i++) {
        fds[i] = socket(ia->sa_family, SOCK_DGRAM, 0);

        if (fds[i] == -1) {
            rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "can't create %s socket",
                            (ia->sa_family == AF_INET) ? "IPv4" : "IPv6");
            goto failure;
        }

        memcpy(&iac, ia, SA_LEN(ia));
        satosin(&iac)->sin_port = htons(port);

        if (bind(fds[i], sstosa(&iac), SA_LEN(ia)) != 0) {
            if (errno != EADDRINUSE && errno != EACCES) {
                rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "can't bind to the %s port %d",
                                (ia->sa_family == AF_INET) ? "IPv4" : "IPv6", port);
            } else {
                rval = -2;
            }

            goto failure;
        }

        port++;

        if ((ia->sa_family == AF_INET) && (cf->tos >= 0) &&
                (setsockopt(fds[i], IPPROTO_IP, IP_TOS, &cf->tos, sizeof(cf->tos)) == -1))
            rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "unable to set TOS to %d", cf->tos);

        flags = fcntl(fds[i], F_GETFL);
        fcntl(fds[i], F_SETFL, flags | O_NONBLOCK);
    }

    return 0;

failure:

    for (i = 0; i < 2; i++)
        if (fds[i] != -1) {
            close(fds[i]);
            fds[i] = -1;
        }

    return rval;
}
Ejemplo n.º 16
0
/*
 * Return the name of the network whose address is given.
 */
const char *
netname(struct sockaddr *sa, struct sockaddr *mask)
{
	switch (sa->sa_family) {
	case AF_INET:
		if (mask != NULL)
			return (netname4(satosin(sa)->sin_addr.s_addr,
			    satosin(mask)->sin_addr.s_addr));
		else
			return (netname4(satosin(sa)->sin_addr.s_addr,
			    INADDR_ANY));
		break;
#ifdef INET6
	case AF_INET6:
		return (netname6(satosin6(sa), satosin6(mask)));
#endif /* INET6 */
	default:
		return (NULL);
	}
}
Ejemplo n.º 17
0
static int
prepare_pkt_hdr_pcap(struct rtpp_session *sp, struct rtp_packet *packet, struct pkt_hdr_pcap *hdrp)
{

    if (packet->rtime == -1) {
	rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "can't get current time");
	return -1;
    }

    if (sstosa(&packet->raddr)->sa_family != AF_INET) {
	rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "only AF_INET pcap format is supported");
	return -1;
    }

    memset(hdrp, 0, sizeof(*hdrp));
    dtime2ts(packet->rtime, &(hdrp->pcaprec_hdr.ts_sec), &(hdrp->pcaprec_hdr.ts_usec));
    hdrp->pcaprec_hdr.orig_len = hdrp->pcaprec_hdr.incl_len = sizeof(*hdrp) -
      sizeof(hdrp->pcaprec_hdr) + packet->size;

    hdrp->family = sstosa(&packet->raddr)->sa_family;

    /* Prepare fake IP header */
    hdrp->iphdr.ip_v = 4;
    hdrp->iphdr.ip_hl = sizeof(hdrp->iphdr) >> 2;
    hdrp->iphdr.ip_len = htons(sizeof(hdrp->iphdr) + sizeof(hdrp->udphdr) + packet->size);
    hdrp->iphdr.ip_src = satosin(&(packet->raddr))->sin_addr;
    hdrp->iphdr.ip_dst = satosin(packet->laddr)->sin_addr;
    hdrp->iphdr.ip_p = IPPROTO_UDP;
    hdrp->iphdr.ip_id = htons(ip_id++);
    hdrp->iphdr.ip_ttl = 127;
    hdrp->iphdr.ip_sum = rtpp_in_cksum(&(hdrp->iphdr), sizeof(hdrp->iphdr));

    /* Prepare fake UDP header */
    hdrp->udphdr.uh_sport = satosin(&packet->raddr)->sin_port;
    hdrp->udphdr.uh_dport = htons(packet->rport);
    hdrp->udphdr.uh_ulen = htons(sizeof(hdrp->udphdr) + packet->size);

    return 0;
}
Ejemplo n.º 18
0
/*
 * Do what we need to do when inserting a route.
 */
static struct radix_node *
in_addroute(void *v_arg, void *n_arg, struct radix_node_head *head,
    struct radix_node *treenodes)
{
	struct rtentry *rt = (struct rtentry *)treenodes;
	struct sockaddr_in *sin = (struct sockaddr_in *)rt_key(rt);

	RADIX_NODE_HEAD_WLOCK_ASSERT(head);
	/*
	 * A little bit of help for both IP output and input:
	 *   For host routes, we make sure that RTF_BROADCAST
	 *   is set for anything that looks like a broadcast address.
	 *   This way, we can avoid an expensive call to in_broadcast()
	 *   in ip_output() most of the time (because the route passed
	 *   to ip_output() is almost always a host route).
	 *
	 *   We also do the same for local addresses, with the thought
	 *   that this might one day be used to speed up ip_input().
	 *
	 * We also mark routes to multicast addresses as such, because
	 * it's easy to do and might be useful (but this is much more
	 * dubious since it's so easy to inspect the address).
	 */
	if (rt->rt_flags & RTF_HOST) {
		if (in_broadcast(sin->sin_addr, rt->rt_ifp)) {
			rt->rt_flags |= RTF_BROADCAST;
		} else if (satosin(rt->rt_ifa->ifa_addr)->sin_addr.s_addr ==
		    sin->sin_addr.s_addr) {
			rt->rt_flags |= RTF_LOCAL;
		}
	}
	if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)))
		rt->rt_flags |= RTF_MULTICAST;

	if (rt->rt_ifp != NULL) {

		/*
		 * Check route MTU:
		 * inherit interface MTU if not set or
		 * check if MTU is too large.
		 */
		if (rt->rt_mtu == 0) {
			rt->rt_mtu = rt->rt_ifp->if_mtu;
		} else if (rt->rt_mtu > rt->rt_ifp->if_mtu)
			rt->rt_mtu = rt->rt_ifp->if_mtu;
	}

	return (rn_addroute(v_arg, n_arg, head, treenodes));
}
Ejemplo n.º 19
0
int
add_addr(struct sockaddr *addr, struct pf_pool *pfp)
{
	if (addr->sa_family == AF_INET) {
		memcpy(&pfp->addr.v.a.addr.v4,
		    &satosin(addr)->sin_addr.s_addr, 4);
		memset(&pfp->addr.v.a.mask.addr8, 255, 4);
	} else {
		memcpy(&pfp->addr.v.a.addr.v6,
		    &satosin6(addr)->sin6_addr.s6_addr, 16);
		memset(&pfp->addr.v.a.mask.addr8, 255, 16);
	}
	pfp->addr.type = PF_ADDR_ADDRMASK;
	return (0);
}
Ejemplo n.º 20
0
__private_extern__ uint32_t
inpcb_find_anypcb_byaddr(struct ifaddr *ifa, struct inpcbinfo *pcbinfo)
{
	struct inpcb *inp;
	inp_gen_t gencnt = pcbinfo->ipi_gencnt;
	struct socket *so = NULL;
	int af;

	if ((ifa->ifa_addr->sa_family != AF_INET) &&
	    (ifa->ifa_addr->sa_family != AF_INET6)) {
		return (0);
	}

	lck_rw_lock_shared(pcbinfo->ipi_lock);
	for (inp = LIST_FIRST(pcbinfo->ipi_listhead);
	    inp != NULL; inp = LIST_NEXT(inp, inp_list)) {

		if (inp->inp_gencnt <= gencnt &&
		    inp->inp_state != INPCB_STATE_DEAD &&
		    inp->inp_socket != NULL) {
			so = inp->inp_socket;
			af = SOCK_DOM(so);
			if (af != ifa->ifa_addr->sa_family)
				continue;
			if (inp->inp_last_outifp != ifa->ifa_ifp)
				continue;

			if (af == AF_INET) {
				if (inp->inp_laddr.s_addr ==
				    (satosin(ifa->ifa_addr))->sin_addr.s_addr) {
					lck_rw_done(pcbinfo->ipi_lock);
					return (1);
				}
			}
			if (af == AF_INET6) {
				if (IN6_ARE_ADDR_EQUAL(IFA_IN6(ifa),
				    &inp->in6p_laddr)) {
					lck_rw_done(pcbinfo->ipi_lock);
					return (1);
				}
			}
		}
	}
	lck_rw_done(pcbinfo->ipi_lock);
	return (0);
}
Ejemplo n.º 21
0
/** Create and start a new answering machine from the given info */
void AnswMachine::launchAnswMach(NEW_CTL_MSG msginfo, int mode) 
 {
  if ((fork()) == 0) /* let's fork to let the daemon process other messages */
    {

#define	satosin(sa)	((struct sockaddr_in *)(sa))

        AnswMachine * am = new AnswMachine(
             (satosin(&msginfo.ctl_addr))->sin_addr, /* Caller's machine address */
             msginfo.r_name,
             msginfo.l_name,
             mode);
        am->start();
        delete am;

        // exit the child
        exit(-1);
    }
 }
Ejemplo n.º 22
0
void
do_announce(CTL_MSG *mp, CTL_RESPONSE *rp)
{
	struct hostent *hp;
	CTL_MSG *ptr;
	int result;

	/* see if the user is logged */
	result = find_user(mp->r_name, mp->r_tty);
	if (result != SUCCESS) {
		rp->answer = result;
		return;
	}
#define	satosin(sa)	((struct sockaddr_in *)(void *)(sa))
	hp = gethostbyaddr(&satosin(&mp->ctl_addr)->sin_addr,
		sizeof (struct in_addr), AF_INET);
	if (hp == NULL) {
		rp->answer = MACHINE_UNKNOWN;
		return;
	}
	ptr = find_request(mp);
	if (ptr == NULL) {
		insert_table(mp, rp);
		rp->answer = announce(mp, hp->h_name);
		return;
	}
	if (mp->id_num > ptr->id_num) {
		/*
		 * This is an explicit re-announce, so update the id_num
		 * field to avoid duplicates and re-announce the talk.
		 */
		ptr->id_num = new_id();
		rp->id_num = htonl(ptr->id_num);
		rp->answer = announce(mp, hp->h_name);
	} else {
		/* a duplicated request, so ignore it */
		rp->id_num = htonl(ptr->id_num);
		rp->answer = SUCCESS;
	}
}
Ejemplo n.º 23
0
int
in_pcbladdr(struct inpcb *inp, struct mbuf *nam, struct sockaddr_in **plocal_sin)
{
	struct in_ifaddr *ia;
	register struct sockaddr_in *sin = mtod(nam, struct sockaddr_in *);

	if (nam->m_len != sizeof (*sin))
		return (EINVAL);
	if (sin->sin_family != AF_INET)
		return (EAFNOSUPPORT);
	if (sin->sin_port == 0)
		return (EADDRNOTAVAIL);
	if (in_ifaddr) {
		/*
		 * If the destination address is INADDR_ANY,
		 * use the primary local address.
		 * If the supplied address is INADDR_BROADCAST,
		 * and the primary interface supports broadcast,
		 * choose the broadcast address for that interface.
		 */
#define	satosin(sa)	((struct sockaddr_in *)(sa))
#define sintosa(sin)	((struct sockaddr *)(sin))
#define ifatoia(ifa)	((struct in_ifaddr *)(ifa))
		if (sin->sin_addr.s_addr == INADDR_ANY)
		    sin->sin_addr = IA_SIN(in_ifaddr)->sin_addr;
		else if (sin->sin_addr.s_addr == (u_long)INADDR_BROADCAST &&
		  (in_ifaddr->ia_ifp->if_flags & IFF_BROADCAST))
		    sin->sin_addr = satosin(&in_ifaddr->ia_broadaddr)->sin_addr;
	}
	if (inp->inp_laddr.s_addr == INADDR_ANY) {
		register struct route *ro;

		ia = (struct in_ifaddr *)0;
		/*
		 * If route is known or can be allocated now,
		 * our src addr is taken from the i/f, else punt.
		 */
		ro = &inp->inp_route;
		if (ro->ro_rt &&
		    (satosin(&ro->ro_dst)->sin_addr.s_addr !=
			sin->sin_addr.s_addr ||
		    inp->inp_socket->so_options & SO_DONTROUTE)) {
			RTFREE(ro->ro_rt);
			ro->ro_rt = (struct rtentry *)0;
		}
		if ((inp->inp_socket->so_options & SO_DONTROUTE) == 0 && /*XXX*/
		    (ro->ro_rt == (struct rtentry *)0 ||
		    ro->ro_rt->rt_ifp == (struct ifnet *)0)) {
			/* No route yet, so try to acquire one */
			ro->ro_dst.sa_family = AF_INET;
			ro->ro_dst.sa_len = sizeof(struct sockaddr_in);
			((struct sockaddr_in *) &ro->ro_dst)->sin_addr =
				sin->sin_addr;
			rtalloc(ro);
		}
		/*
		 * If we found a route, use the address
		 * corresponding to the outgoing interface
		 * unless it is the loopback (in case a route
		 * to our address on another net goes to loopback).
		 */
		if (ro->ro_rt && !(ro->ro_rt->rt_ifp->if_flags & IFF_LOOPBACK))
			ia = ifatoia(ro->ro_rt->rt_ifa);
		if (ia == 0) {
			u_short fport = sin->sin_port;

			sin->sin_port = 0;
			ia = ifatoia(ifa_ifwithdstaddr(sintosa(sin)));
			if (ia == 0)
				ia = ifatoia(ifa_ifwithnet(sintosa(sin)));
			sin->sin_port = fport;
			if (ia == 0)
				ia = in_ifaddr;
			if (ia == 0)
				return (EADDRNOTAVAIL);
		}
		/*
		 * If the destination address is multicast and an outgoing
		 * interface has been set as a multicast option, use the
		 * address of that interface as our source address.
		 */
		if (IN_MULTICAST(ntohl(sin->sin_addr.s_addr)) &&
		    inp->inp_moptions != NULL) {
			struct ip_moptions *imo;
			struct ifnet *ifp;

			imo = inp->inp_moptions;
			if (imo->imo_multicast_ifp != NULL) {
				ifp = imo->imo_multicast_ifp;
				for (ia = in_ifaddr; ia; ia = ia->ia_next)
					if (ia->ia_ifp == ifp)
						break;
				if (ia == 0)
					return (EADDRNOTAVAIL);
			}
		}
	/*
	 * Don't do pcblookup call here; return interface in plocal_sin
	 * and exit to caller, that will do the lookup.
	 */
		*plocal_sin = &ia->ia_addr;

	}
	return(0);
}
Ejemplo n.º 24
0
struct ul_opts *
rtpp_command_ul_opts_parse(struct cfg *cf, struct rtpp_command *cmd)
{
    int len, tpf, n, i;
    char c;
    char *cp, *t;
    const char *errmsg;
    struct sockaddr_storage tia;
    struct ul_opts *ulop;

    ulop = rtpp_zmalloc(sizeof(struct ul_opts));
    if (ulop == NULL) {
        reply_error(cmd, ECODE_NOMEM_1);
        goto err_undo_0;
    }
    ul_opts_init(cf, ulop);
    if (cmd->cca.op == UPDATE && cmd->argc > 6) {
        if (cmd->argc == 8) {
            ulop->notify_socket = cmd->argv[6];
            ulop->notify_tag = cmd->argv[7];
        } else {
            ulop->notify_socket = cmd->argv[5];
            ulop->notify_tag = cmd->argv[6];
            cmd->cca.to_tag = NULL;
        }
        len = url_unquote((uint8_t *)ulop->notify_tag, strlen(ulop->notify_tag));
        if (len == -1) {
            RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR,
              "command syntax error - invalid URL encoding");
            reply_error(cmd, ECODE_PARSE_10);
            goto err_undo_1;
        }
        ulop->notify_tag[len] = '\0';
    }
    ulop->addr = cmd->argv[2];
    ulop->port = cmd->argv[3];
    /* Process additional command modifiers */
    for (cp = cmd->argv[0] + 1; *cp != '\0'; cp++) {
        switch (*cp) {
        case 'a':
        case 'A':
            ulop->asymmetric = 1;
            break;

        case 'e':
        case 'E':
            if (ulop->lidx < 0 || cf->stable->bindaddr[1] == NULL) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "command syntax error");
                reply_error(cmd, ECODE_PARSE_11);
                goto err_undo_1;
            }
            ulop->lia[ulop->lidx] = cf->stable->bindaddr[1];
            ulop->lidx--;
            break;

        case 'i':
        case 'I':
            if (ulop->lidx < 0 || cf->stable->bindaddr[1] == NULL) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "command syntax error");
                reply_error(cmd, ECODE_PARSE_12);
                goto err_undo_1;
            }
            ulop->lia[ulop->lidx] = cf->stable->bindaddr[0];
            ulop->lidx--;
            break;

        case '6':
            ulop->pf = AF_INET6;
            break;

        case 's':
        case 'S':
            ulop->asymmetric = 0;
            break;

        case 'w':
        case 'W':
            ulop->weak = 1;
            break;

        case 'z':
        case 'Z':
            ulop->requested_ptime = strtol(cp + 1, &cp, 10);
            if (ulop->requested_ptime <= 0) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "command syntax error");
                reply_error(cmd, ECODE_PARSE_13);
                goto err_undo_1;
            }
            cp--;
            break;

        case 'c':
        case 'C':
            cp += 1;
            for (t = cp; *cp != '\0'; cp++) {
                if (!isdigit(*cp) && *cp != ',')
                    break;
            }
            if (t == cp) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "command syntax error");
                reply_error(cmd, ECODE_PARSE_14);
                goto err_undo_1;
            }
            ulop->codecs = malloc(cp - t + 1);
            if (ulop->codecs == NULL) {
                reply_error(cmd, ECODE_NOMEM_2);
                goto err_undo_1;
            }
            memcpy(ulop->codecs, t, cp - t);
            ulop->codecs[cp - t] = '\0';
            cp--;
            break;

        case 'l':
        case 'L':
            len = extractaddr(cp + 1, &t, &cp, &tpf);
            if (len == -1) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "command syntax error");
                reply_error(cmd, ECODE_PARSE_15);
                goto err_undo_1;
            }
            c = t[len];
            t[len] = '\0';
            ulop->local_addr = host2bindaddr(cf, t, tpf, &errmsg);
            if (ulop->local_addr == NULL) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR,
                  "invalid local address: %s: %s", t, errmsg);
                reply_error(cmd, ECODE_INVLARG_1);
                goto err_undo_1;
            }
            t[len] = c;
            cp--;
            break;

        case 'r':
        case 'R':
            len = extractaddr(cp + 1, &t, &cp, &tpf);
            if (len == -1) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "command syntax error");
                reply_error(cmd, ECODE_PARSE_16);
                goto err_undo_1;
            }
            c = t[len];
            t[len] = '\0';
            ulop->local_addr = alloca(sizeof(struct sockaddr_storage));
            n = resolve(ulop->local_addr, tpf, t, SERVICE, AI_PASSIVE);
            if (n != 0) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR,
                  "invalid remote address: %s: %s", t, gai_strerror(n));
                reply_error(cmd, ECODE_INVLARG_2);
                goto err_undo_1;
            }
            if (local4remote(ulop->local_addr, satoss(ulop->local_addr)) == -1) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR,
                  "can't find local address for remote address: %s", t);
                reply_error(cmd, ECODE_INVLARG_3);
                goto err_undo_1;
            }
            ulop->local_addr = addr2bindaddr(cf, ulop->local_addr, &errmsg);
            if (ulop->local_addr == NULL) {
                RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR,
                  "invalid local address: %s", errmsg);
                reply_error(cmd, ECODE_INVLARG_4);
                goto err_undo_1;
            }
            t[len] = c;
            cp--;
            break;

        case 'n':
        case 'N':
            ulop->new_port = 1;
            break;

        default:
            RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "unknown command modifier `%c'",
              *cp);
            break;
        }
    }
    if (ulop->addr != NULL && ulop->port != NULL && strlen(ulop->addr) >= 7) {
        n = resolve(sstosa(&tia), ulop->pf, ulop->addr, ulop->port, AI_NUMERICHOST);
        if (n == 0) {
            if (!ishostnull(sstosa(&tia))) {
                for (i = 0; i < 2; i++) {
                    ulop->ia[i] = malloc(SS_LEN(&tia));
                    if (ulop->ia[i] == NULL) {
                        reply_error(cmd, ECODE_NOMEM_3);
                        goto err_undo_1;
                    }
                    memcpy(ulop->ia[i], &tia, SS_LEN(&tia));
                }
                /* Set port for RTCP, will work both for IPv4 and IPv6 */
                n = ntohs(satosin(ulop->ia[1])->sin_port);
                satosin(ulop->ia[1])->sin_port = htons(n + 1);
            }
        } else {
            RTPP_LOG(cf->stable->glog, RTPP_LOG_ERR, "getaddrinfo(pf=%d, addr=%s, port=%s): %s",
              ulop->pf, ulop->addr, ulop->port, gai_strerror(n));
        }
    }
    return (ulop);

err_undo_1:
    rtpp_command_ul_opts_free(ulop);
err_undo_0:
    return (NULL);
}
Ejemplo n.º 25
0
int
handle_command(struct cfg *cf, int controlfd, double dtime)
{
    int len, argc, i, pidx, asymmetric;
    int external, pf, lidx, playcount, weak, tpf;
    int fds[2], lport, n;
    socklen_t rlen;
    char buf[1024 * 8];
    char *cp, *call_id, *from_tag, *to_tag, *addr, *port, *cookie;
    char *pname, *codecs, *recording_name, *t;
    struct rtpp_session *spa, *spb;
    char **ap, *argv[10];
    const char *rname, *errmsg;
    struct sockaddr *ia[2], *lia[2];
    struct sockaddr_storage raddr;
    int requested_nsamples;
    enum {DELETE, RECORD, PLAY, NOPLAY, COPY, UPDATE, LOOKUP, QUERY} op;
    int max_argc;
    char *socket_name_u, *notify_tag;
    struct sockaddr *local_addr;
    char c;

    requested_nsamples = -1;
    ia[0] = ia[1] = NULL;
    spa = spb = NULL;
    lia[0] = lia[1] = cf->bindaddr[0];
    lidx = 1;
    fds[0] = fds[1] = -1;
    recording_name = NULL;
    socket_name_u = notify_tag = NULL;
    local_addr = NULL;
    codecs = NULL;

    if (cf->umode == 0) {
	for (;;) {
	    len = read(controlfd, buf, sizeof(buf) - 1);
	    if (len != -1 || (errno != EAGAIN && errno != EINTR))
		break;
	    sched_yield();
	}
    } else {
	rlen = sizeof(raddr);
	len = recvfrom(controlfd, buf, sizeof(buf) - 1, 0,
	  sstosa(&raddr), &rlen);
    }
    if (len == -1) {
	if (errno != EAGAIN && errno != EINTR)
	    rtpp_log_ewrite(RTPP_LOG_ERR, cf->glog, "can't read from control socket");
	return -1;
    }
    buf[len] = '\0';

    rtpp_log_write(RTPP_LOG_DBUG, cf->glog, "received command \"%s\"", buf);

    cp = buf;
    argc = 0;
    memset(argv, 0, sizeof(argv));
    for (ap = argv; (*ap = rtpp_strsep(&cp, "\r\n\t ")) != NULL;)
	if (**ap != '\0') {
	    argc++;
	    if (++ap >= &argv[10])
		break;
	}
    cookie = NULL;
    if (argc < 1 || (cf->umode != 0 && argc < 2)) {
	rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	reply_error(cf, controlfd, &raddr, rlen, cookie, 0);
	return 0;
    }

    /* Stream communication mode doesn't use cookie */
    if (cf->umode != 0) {
	cookie = argv[0];
	for (i = 1; i < argc; i++)
	    argv[i - 1] = argv[i];
	argc--;
	argv[argc] = NULL;
    } else {
	cookie = NULL;
    }

    addr = port = NULL;
    switch (argv[0][0]) {
    case 'u':
    case 'U':
	/* U[opts] callid remote_ip remote_port from_tag [to_tag] */
	op = UPDATE;
	rname = "update/create";
	break;

    case 'l':
    case 'L':
	op = LOOKUP;
	rname = "lookup";
	break;

    case 'd':
    case 'D':
	op = DELETE;
	rname = "delete";
	break;

    case 'p':
    case 'P':
	/*
	 * P callid pname codecs from_tag to_tag
	 *
	 *   <codecs> could be either comma-separated list of supported
	 *   payload types or word "session" (without quotes), in which
	 *   case list saved on last session update will be used instead.
	 */
	op = PLAY;
	rname = "play";
	playcount = 1;
	pname = argv[2];
	codecs = argv[3];
	break;

    case 'r':
    case 'R':
	op = RECORD;
	rname = "record";
	break;

    case 'c':
    case 'C':
	op = COPY;
	rname = "copy";
	break;

    case 's':
    case 'S':
	op = NOPLAY;
	rname = "noplay";
	break;

    case 'v':
    case 'V':
	if (argv[0][1] == 'F' || argv[0][1] == 'f') {
	    int i, known;
	    /*
	     * Wait for protocol version datestamp and check whether we
	     * know it.
	     */
	    if (argc != 2 && argc != 3) {
		rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		reply_error(cf, controlfd, &raddr, rlen, cookie, 2);
		return 0;
	    }
	    /*
	     * Only list 20081224 protocol mod as supported if
	     * user actually enabled notification with -n
	     */
	    if (strcmp(argv[1], "20081224") == 0 &&
	      cf->timeout_handler.socket_name == NULL) {
		reply_number(cf, controlfd, &raddr, rlen, cookie, 0);
		return 0;
	    }
	    for (known = i = 0; proto_caps[i].pc_id != NULL; ++i) {
		if (!strcmp(argv[1], proto_caps[i].pc_id)) {
		    known = 1;
		    break;
		}
	    }
	    reply_number(cf, controlfd, &raddr, rlen, cookie, known);
	    return 0;
	}
	if (argc != 1 && argc != 2) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 2);
	    return 0;
	}
	/* This returns base version. */
	reply_number(cf, controlfd, &raddr, rlen, cookie, CPROTOVER);
	return 0;

    case 'i':
    case 'I':
	if (cookie == NULL)
	    len = sprintf(buf, "sessions created: %llu\nactive sessions: %d\n"
	      "active streams: %d\n", cf->sessions_created,
	      cf->sessions_active, cf->nsessions / 2);
	else
	    len = sprintf(buf, "%s sessions created: %llu\nactive sessions: %d\n"
	      "active streams: %d\n", cookie, cf->sessions_created,
	      cf->sessions_active, cf->nsessions / 2);
	for (i = 1; i < cf->nsessions; i++) {
	    char addrs[4][256];

	    spa = cf->sessions[i];
	    if (spa == NULL || spa->sidx[0] != i)
		continue;
	    /* RTCP twin session */
	    if (spa->rtcp == NULL) {
		spb = spa->rtp;
		buf[len++] = '\t';
	    } else {
		spb = spa->rtcp;
		buf[len++] = '\t';
		buf[len++] = 'C';
		buf[len++] = ' ';
	    }

	    addr2char_r(spb->laddr[1], addrs[0], sizeof(addrs[0]));
	    if (spb->addr[1] == NULL) {
		strcpy(addrs[1], "NONE");
	    } else {
		sprintf(addrs[1], "%s:%d", addr2char(spb->addr[1]),
		  addr2port(spb->addr[1]));
	    }
	    addr2char_r(spb->laddr[0], addrs[2], sizeof(addrs[2]));
	    if (spb->addr[0] == NULL) {
		strcpy(addrs[3], "NONE");
	    } else {
		sprintf(addrs[3], "%s:%d", addr2char(spb->addr[0]),
		  addr2port(spb->addr[0]));
	    }

	    len += sprintf(buf + len,
	      "%s/%s: caller = %s:%d/%s, callee = %s:%d/%s, "
	      "stats = %lu/%lu/%lu/%lu, ttl = %d/%d\n",
	      spb->call_id, spb->tag, addrs[0], spb->ports[1], addrs[1],
	      addrs[2], spb->ports[0], addrs[3], spa->pcount[0], spa->pcount[1],
	      spa->pcount[2], spa->pcount[3], spb->ttl[0], spb->ttl[1]);
	    if (len + 512 > sizeof(buf)) {
		doreply(cf, controlfd, buf, len, &raddr, rlen);
		len = 0;
	    }
	}
	if (len > 0)
	    doreply(cf, controlfd, buf, len, &raddr, rlen);;
	return 0;
	break;

    case 'q':
    case 'Q':
	op = QUERY;
	rname = "query";
	break;

    case 'x':
    case 'X':
        /* Delete all active sessions */
        rtpp_log_write(RTPP_LOG_INFO, cf->glog, "deleting all active sessions");
        for (i = 1; i < cf->nsessions; i++) {
	    spa = cf->sessions[i];
	    if (spa == NULL || spa->sidx[0] != i)
		continue;
	    /* Skip RTCP twin session */
	    if (spa->rtcp != NULL) {
		remove_session(cf, spa);
	    }
        }
        reply_ok(cf, controlfd, &raddr, rlen, cookie);
        return 0;
        break;

    default:
	rtpp_log_write(RTPP_LOG_ERR, cf->glog, "unknown command");
	reply_error(cf, controlfd, &raddr, rlen, cookie, 3);
	return 0;
    }
    call_id = argv[1];
    if (op == UPDATE || op == LOOKUP || op == PLAY) {
	max_argc = (op == UPDATE ? 8 : 6);
	if (argc < 5 || argc > max_argc) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 4);
	    return 0;
	}
	from_tag = argv[4];
	to_tag = argv[5];
	if (op == PLAY && argv[0][1] != '\0')
	    playcount = atoi(argv[0] + 1);
	if (op == UPDATE && argc > 6) {
	    socket_name_u = argv[6];
	    if (strncmp("unix:", socket_name_u, 5) == 0)
		socket_name_u += 5;
	    if (argc == 8) {
		notify_tag = argv[7];
		len = url_unquote((uint8_t *)notify_tag, strlen(notify_tag));
		if (len == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "command syntax error - invalid URL encoding");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 4);
		    return 0;
		}
		notify_tag[len] = '\0';
	    }
	}
    }
    if (op == COPY) {
	if (argc < 4 || argc > 5) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
	    return 0;
	}
	recording_name = argv[2];
	from_tag = argv[3];
	to_tag = argv[4];
    }
    if (op == DELETE || op == RECORD || op == NOPLAY || op == QUERY) {
	if (argc < 3 || argc > 4) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
	    return 0;
	}
	from_tag = argv[2];
	to_tag = argv[3];
    }
    if (op == DELETE || op == RECORD || op == COPY || op == NOPLAY) {
	/* D, R and S commands don't take any modifiers */
	if (argv[0][1] != '\0') {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
	    return 0;
	}
    }
    if (op == UPDATE || op == LOOKUP || op == DELETE) {
	addr = argv[2];
	port = argv[3];
	/* Process additional command modifiers */
	external = 1;
	/* In bridge mode all clients are assumed to be asymmetric */
	asymmetric = (cf->bmode != 0) ? 1 : 0;
	pf = AF_INET;
	weak = 0;
	for (cp = argv[0] + 1; *cp != '\0'; cp++) {
	    switch (*cp) {
	    case 'a':
	    case 'A':
		asymmetric = 1;
		break;

	    case 'e':
	    case 'E':
		if (lidx < 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		lia[lidx] = cf->bindaddr[1];
		lidx--;
		break;

	    case 'i':
	    case 'I':
		if (lidx < 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		lia[lidx] = cf->bindaddr[0];
		lidx--;
		break;

	    case '6':
		pf = AF_INET6;
		break;

	    case 's':
	    case 'S':
		asymmetric = 0;
		break;

	    case 'w':
	    case 'W':
		weak = 1;
		break;

	    case 'z':
	    case 'Z':
		requested_nsamples = (strtol(cp + 1, &cp, 10) / 10) * 80;
		if (requested_nsamples <= 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		cp--;
		break;

	    case 'c':
	    case 'C':
		cp += 1;
		for (t = cp; *cp != '\0'; cp++) {
		    if (!isdigit(*cp) && *cp != ',')
			break;
		}
		if (t == cp) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		codecs = alloca(cp - t + 1);
		memcpy(codecs, t, cp - t);
		codecs[cp - t] = '\0';
		cp--;
		break;

	    case 'l':
	    case 'L':
		len = extractaddr(cp + 1, &t, &cp, &tpf);
		if (len == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		c = t[len];
		t[len] = '\0';
		local_addr = host2bindaddr(cf, t, tpf, &errmsg);
		if (local_addr == NULL) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "invalid local address: %s: %s", t, errmsg);
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		t[len] = c;
		cp--;
		break;

	    case 'r':
	    case 'R':
		len = extractaddr(cp + 1, &t, &cp, &tpf);
		if (len == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "command syntax error");
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		c = t[len];
		t[len] = '\0';
		local_addr = alloca(sizeof(struct sockaddr_storage));
		n = resolve(local_addr, tpf, t, SERVICE, AI_PASSIVE);
		if (n != 0) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "invalid remote address: %s: %s", t, gai_strerror(n));
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		if (local4remote(cf, local_addr, satoss(local_addr)) == -1) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "can't find local address for remote address: %s", t);
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		local_addr = addr2bindaddr(cf, local_addr, &errmsg);
		if (local_addr == NULL) {
		    rtpp_log_write(RTPP_LOG_ERR, cf->glog,
		      "invalid local address: %s", errmsg);
		    reply_error(cf, controlfd, &raddr, rlen, cookie, 1);
		    return 0;
		}
		t[len] = c;
		cp--;
		break;

	    default:
		rtpp_log_write(RTPP_LOG_ERR, cf->glog, "unknown command modifier `%c'",
		  *cp);
		break;
	    }
	}
	if (op != DELETE && addr != NULL && port != NULL && strlen(addr) >= 7) {
	    struct sockaddr_storage tia;

	    if ((n = resolve(sstosa(&tia), pf, addr, port,
	      AI_NUMERICHOST)) == 0) {
		if (!ishostnull(sstosa(&tia))) {
		    for (i = 0; i < 2; i++) {
			ia[i] = malloc(SS_LEN(&tia));
			if (ia[i] == NULL) {
			    handle_nomem(cf, controlfd, &raddr, rlen, cookie,
			      5, ia, fds, spa, spb);
			    return 0;
			}
			memcpy(ia[i], &tia, SS_LEN(&tia));
		    }
		    /* Set port for RTCP, will work both for IPv4 and IPv6 */
		    n = ntohs(satosin(ia[1])->sin_port);
		    satosin(ia[1])->sin_port = htons(n + 1);
		}
	    } else {
		rtpp_log_write(RTPP_LOG_ERR, cf->glog, "getaddrinfo: %s",
		  gai_strerror(n));
	    }
	}
    }

    /*
     * Record and delete need special handling since they apply to all
     * streams in the session.
     */
    switch (op) {
    case DELETE:
	i = handle_delete(cf, call_id, from_tag, to_tag, weak);
	break;

    case RECORD:
	i = handle_record(cf, call_id, from_tag, to_tag);
	break;

    default:
	i = find_stream(cf, call_id, from_tag, to_tag, &spa);
	if (i != -1 && op != UPDATE)
	    i = NOT(i);
	break;
    }

    if (i == -1 && op != UPDATE) {
	rtpp_log_write(RTPP_LOG_INFO, cf->glog,
	  "%s request failed: session %s, tags %s/%s not found", rname,
	  call_id, from_tag, to_tag != NULL ? to_tag : "NONE");
	if (op == LOOKUP) {
	    for (i = 0; i < 2; i++)
		if (ia[i] != NULL)
		    free(ia[i]);
	    reply_port(cf, controlfd, &raddr, rlen, cookie, 0, lia);
	    return 0;
	}
	reply_error(cf, controlfd, &raddr, rlen, cookie, 8);
	return 0;
    }

    switch (op) {
    case DELETE:
    case RECORD:
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case NOPLAY:
	handle_noplay(cf, spa, i);
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case PLAY:
	handle_noplay(cf, spa, i);
	if (strcmp(codecs, "session") == 0) {
	    if (spa->codecs[i] == NULL) {
		reply_error(cf, controlfd, &raddr, rlen, cookie, 6);
		return 0;
	    }
	    codecs = spa->codecs[i];
	}
	if (playcount != 0 && handle_play(cf, spa, i, codecs, pname, playcount) != 0) {
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 6);
	    return 0;
	}
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case COPY:
	handle_copy(cf, spa, i, recording_name);
	reply_ok(cf, controlfd, &raddr, rlen, cookie);
	return 0;

    case QUERY:
	handle_query(cf, controlfd, &raddr, rlen, cookie, spa, i);
	return 0;

    case LOOKUP:
    case UPDATE:
	/* those are handled below */
	break;

    default:
	/* Programmatic error, should not happen */
	abort();
    }

    pidx = 1;
    lport = 0;
    if (i != -1) {
	assert(op == UPDATE || op == LOOKUP);
	if (spa->fds[i] == -1) {
	    if (local_addr != NULL) {
		spa->laddr[i] = local_addr;
	    }
	    if (create_listener(cf, spa->laddr[i], &lport, fds) == -1) {
		rtpp_log_write(RTPP_LOG_ERR, spa->log, "can't create listener");
		reply_error(cf, controlfd, &raddr, rlen, cookie, 7);
		return 0;
	    }
	    assert(spa->fds[i] == -1);
	    spa->fds[i] = fds[0];
	    assert(spa->rtcp->fds[i] == -1);
	    spa->rtcp->fds[i] = fds[1];
	    spa->ports[i] = lport;
	    spa->rtcp->ports[i] = lport + 1;
	    spa->complete = spa->rtcp->complete = 1;
	    append_session(cf, spa, i);
	    append_session(cf, spa->rtcp, i);
	}
	if (weak)
	    spa->weak[i] = 1;
	else if (op == UPDATE)
	    spa->strong = 1;
	lport = spa->ports[i];
	lia[0] = spa->laddr[i];
	pidx = (i == 0) ? 1 : 0;
	spa->ttl_mode = cf->ttl_mode;
	spa->ttl[0] = cf->max_ttl;
	spa->ttl[1] = cf->max_ttl;
	if (op == UPDATE) {
	    rtpp_log_write(RTPP_LOG_INFO, spa->log,
	      "adding %s flag to existing session, new=%d/%d/%d",
	      weak ? ( i ? "weak[1]" : "weak[0]" ) : "strong",
	      spa->strong, spa->weak[0], spa->weak[1]);
	}
	rtpp_log_write(RTPP_LOG_INFO, spa->log,
	  "lookup on ports %d/%d, session timer restarted", spa->ports[0],
	  spa->ports[1]);
    } else {
	assert(op == UPDATE);
	rtpp_log_write(RTPP_LOG_INFO, cf->glog,
	  "new session %s, tag %s requested, type %s",
	  call_id, from_tag, weak ? "weak" : "strong");

	if (local_addr != NULL) {
	    lia[0] = lia[1] = local_addr;
	    if (lia[0] == NULL) {
		rtpp_log_write(RTPP_LOG_ERR, spa->log,
		  "can't create listener: %s", t);
		reply_error(cf, controlfd, &raddr, rlen, cookie, 10);
		return 0;
	    }
	}
	if (create_listener(cf, lia[0], &lport, fds) == -1) {
	    rtpp_log_write(RTPP_LOG_ERR, cf->glog, "can't create listener");
	    reply_error(cf, controlfd, &raddr, rlen, cookie, 10);
	    return 0;
	}

	/*
	 * Session creation. If creation is requested with weak flag,
	 * set weak[0].
	 */
	spa = malloc(sizeof(*spa));
	if (spa == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 11, ia,
	      fds, spa, spb);
	    return 0;
	}
	/* spb is RTCP twin session for this one. */
	spb = malloc(sizeof(*spb));
	if (spb == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 12, ia,
	      fds, spa, spb);
	    return 0;
	}
	memset(spa, 0, sizeof(*spa));
	memset(spb, 0, sizeof(*spb));
	for (i = 0; i < 2; i++) {
	    spa->fds[i] = spb->fds[i] = -1;
	    spa->last_update[i] = 0;
	    spb->last_update[i] = 0;
	}
	spa->call_id = strdup(call_id);
	if (spa->call_id == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 13, ia,
	      fds, spa, spb);
	    return 0;
	}
	spb->call_id = spa->call_id;
	spa->tag = strdup(from_tag);
	if (spa->tag == NULL) {
	    handle_nomem(cf, controlfd, &raddr, rlen, cookie, 14, ia,
	      fds, spa, spb);
	    return 0;
	}
	spb->tag = spa->tag;
	for (i = 0; i < 2; i++) {
	    spa->rrcs[i] = NULL;
	    spb->rrcs[i] = NULL;
	    spa->laddr[i] = lia[i];
	    spb->laddr[i] = lia[i];
	}
	spa->strong = spa->weak[0] = spa->weak[1] = 0;
	if (weak)
	    spa->weak[0] = 1;
	else
	    spa->strong = 1;
	assert(spa->fds[0] == -1);
	spa->fds[0] = fds[0];
	assert(spb->fds[0] == -1);
	spb->fds[0] = fds[1];
	spa->ports[0] = lport;
	spb->ports[0] = lport + 1;
	spa->ttl[0] = cf->max_ttl;
	spa->ttl[1] = cf->max_ttl;
	spb->ttl[0] = -1;
	spb->ttl[1] = -1;
	spa->log = rtpp_log_open(cf, "rtpproxy", spa->call_id, 0);
	spb->log = spa->log;
	spa->rtcp = spb;
	spb->rtcp = NULL;
	spa->rtp = NULL;
	spb->rtp = spa;
	spa->sridx = spb->sridx = -1;

	append_session(cf, spa, 0);
	append_session(cf, spa, 1);
	append_session(cf, spb, 0);
	append_session(cf, spb, 1);

	hash_table_append(cf, spa);

	cf->sessions_created++;
	cf->sessions_active++;
	/*
	 * Each session can consume up to 5 open file descriptors (2 RTP,
	 * 2 RTCP and 1 logging) so that warn user when he is likely to
	 * exceed 80% mark on hard limit.
	 */
	if (cf->sessions_active > (cf->nofile_limit.rlim_max * 80 / (100 * 5)) &&
	  cf->nofile_limit_warned == 0) {
	    cf->nofile_limit_warned = 1;
	    rtpp_log_write(RTPP_LOG_WARN, cf->glog, "passed 80%% "
	      "threshold on the open file descriptors limit (%d), "
	      "consider increasing the limit using -L command line "
	      "option", (int)cf->nofile_limit.rlim_max);
	}

	rtpp_log_write(RTPP_LOG_INFO, spa->log, "new session on a port %d created, "
	  "tag %s", lport, from_tag);
	if (cf->record_all != 0) {
	    handle_copy(cf, spa, 0, NULL);
	    handle_copy(cf, spa, 1, NULL);
	}
    }

    if (op == UPDATE) {
	if (cf->timeout_handler.socket_name == NULL && socket_name_u != NULL)
	    rtpp_log_write(RTPP_LOG_ERR, spa->log, "must permit notification socket with -n");
	if (spa->timeout_data.notify_tag != NULL) {
	    free(spa->timeout_data.notify_tag);
	    spa->timeout_data.notify_tag = NULL;
	}
	if (cf->timeout_handler.socket_name != NULL && socket_name_u != NULL) {
	    if (strcmp(cf->timeout_handler.socket_name, socket_name_u) != 0) {
		rtpp_log_write(RTPP_LOG_ERR, spa->log, "invalid socket name %s", socket_name_u);
		socket_name_u = NULL;
	    } else {
		rtpp_log_write(RTPP_LOG_INFO, spa->log, "setting timeout handler");
		spa->timeout_data.handler = &cf->timeout_handler;
		spa->timeout_data.notify_tag = strdup(notify_tag);
	    }
	} else if (socket_name_u == NULL && spa->timeout_data.handler != NULL) {
	    spa->timeout_data.handler = NULL;
	    rtpp_log_write(RTPP_LOG_INFO, spa->log, "disabling timeout handler");
	}
    }

    if (ia[0] != NULL && ia[1] != NULL) {
        if (spa->addr[pidx] != NULL)
            spa->last_update[pidx] = dtime;
        if (spa->rtcp->addr[pidx] != NULL)
            spa->rtcp->last_update[pidx] = dtime;
	/*
	 * Unless the address provided by client historically
	 * cannot be trusted and address is different from one
	 * that we recorded update it.
	 */
	if (spa->untrusted_addr[pidx] == 0 && !(spa->addr[pidx] != NULL &&
	  SA_LEN(ia[0]) == SA_LEN(spa->addr[pidx]) &&
	  memcmp(ia[0], spa->addr[pidx], SA_LEN(ia[0])) == 0)) {
	    rtpp_log_write(RTPP_LOG_INFO, spa->log, "pre-filling %s's address "
	      "with %s:%s", (pidx == 0) ? "callee" : "caller", addr, port);
	    if (spa->addr[pidx] != NULL) {
	        if (spa->canupdate[pidx] == 0) {
	            if (spa->prev_addr[pidx] != NULL)
	                 free(spa->prev_addr[pidx]);
	            spa->prev_addr[pidx] = spa->addr[pidx];
	        } else {
		    free(spa->addr[pidx]);
		}
	    }
	    spa->addr[pidx] = ia[0];
	    ia[0] = NULL;
	}
	if (spa->rtcp->untrusted_addr[pidx] == 0 && !(spa->rtcp->addr[pidx] != NULL &&
	  SA_LEN(ia[1]) == SA_LEN(spa->rtcp->addr[pidx]) &&
	  memcmp(ia[1], spa->rtcp->addr[pidx], SA_LEN(ia[1])) == 0)) {
	    if (spa->rtcp->addr[pidx] != NULL) {
	        if (spa->rtcp->canupdate[pidx] == 0) {
	            if (spa->rtcp->prev_addr[pidx] != NULL)
	                free(spa->rtcp->prev_addr[pidx]);
	            spa->rtcp->prev_addr[pidx] = spa->rtcp->addr[pidx];
	        } else {
		    free(spa->rtcp->addr[pidx]);
		}
	    }
	    spa->rtcp->addr[pidx] = ia[1];
	    ia[1] = NULL;
	}
    }
    spa->asymmetric[pidx] = spa->rtcp->asymmetric[pidx] = asymmetric;
    spa->canupdate[pidx] = spa->rtcp->canupdate[pidx] = NOT(asymmetric);
    if (spa->codecs[pidx] != NULL) {
	free(spa->codecs[pidx]);
	spa->codecs[pidx] = NULL;
    }
    if (codecs != NULL)
	spa->codecs[pidx] = strdup(codecs);
    if (requested_nsamples > 0) {
	rtpp_log_write(RTPP_LOG_INFO, spa->log, "RTP packets from %s "
	  "will be resized to %d milliseconds",
	  (pidx == 0) ? "callee" : "caller", requested_nsamples / 8);
    } else if (spa->resizers[pidx].output_nsamples > 0) {
	  rtpp_log_write(RTPP_LOG_INFO, spa->log, "Resizing of RTP "
	  "packets from %s has been disabled",
	  (pidx == 0) ? "callee" : "caller");
    }
    spa->resizers[pidx].output_nsamples = requested_nsamples;

    for (i = 0; i < 2; i++)
	if (ia[i] != NULL)
	    free(ia[i]);

    assert(lport != 0);
    reply_port(cf, controlfd, &raddr, rlen, cookie, lport, lia);
    return 0;
}
Ejemplo n.º 26
0
static void
rxmit_packets(struct cfg *cf, struct rtpp_session *sp, int ridx,
  double dtime)
{
    int ndrain, i, port;
    struct rtp_packet *packet = NULL;

    /* Repeat since we may have several packets queued on the same socket */
    for (ndrain = 0; ndrain < 5; ndrain++) {
	if (packet != NULL)
	    rtp_packet_free(packet);

	packet = rtp_recv(sp->fds[ridx]);
	if (packet == NULL)
	    break;
	packet->laddr = sp->laddr[ridx];
	packet->rport = sp->ports[ridx];
	packet->rtime = dtime;

	i = 0;
	if (sp->addr[ridx] != NULL) {
	    /* Check that the packet is authentic, drop if it isn't */
	    if (sp->asymmetric[ridx] == 0) {
		if (memcmp(sp->addr[ridx], &packet->raddr, packet->rlen) != 0) {
		    if (sp->canupdate[ridx] == 0) {
			/*
			 * Continue, since there could be good packets in
			 * queue.
			 */
			continue;
		    }
		    /* Signal that an address has to be updated */
		    i = 1;
		} else if (sp->canupdate[ridx] != 0 &&
		  sp->last_update[ridx] != 0 &&
		  dtime - sp->last_update[ridx] > UPDATE_WINDOW) {
		    sp->canupdate[ridx] = 0;
		}
	    } else {
		/*
		 * For asymmetric clients don't check
		 * source port since it may be different.
		 */
		if (!ishostseq(sp->addr[ridx], sstosa(&packet->raddr)))
		    /*
		     * Continue, since there could be good packets in
		     * queue.
		     */
		    continue;
	    }
	    sp->pcount[ridx]++;
	} else {
	    sp->pcount[ridx]++;
	    sp->addr[ridx] = malloc(packet->rlen);
	    if (sp->addr[ridx] == NULL) {
		sp->pcount[3]++;
		rtpp_log_write(RTPP_LOG_ERR, sp->log,
		  "can't allocate memory for remote address - "
		  "removing session");
		remove_session(cf, GET_RTP(sp));
		/* Break, sp is invalid now */
		break;
	    }
	    /* Signal that an address have to be updated. */
	    i = 1;
	}

	/*
	 * Update recorded address if it's necessary. Set "untrusted address"
	 * flag in the session state, so that possible future address updates
	 * from that client won't get address changed immediately to some
	 * bogus one.
	 */
	if (i != 0) {
	    sp->untrusted_addr[ridx] = 1;
	    memcpy(sp->addr[ridx], &packet->raddr, packet->rlen);
	    if (sp->prev_addr[ridx] == NULL || memcmp(sp->prev_addr[ridx],
	      &packet->raddr, packet->rlen) != 0) {
	        sp->canupdate[ridx] = 0;
	    }

	    port = ntohs(satosin(&packet->raddr)->sin_port);

	    rtpp_log_write(RTPP_LOG_INFO, sp->log,
	      "%s's address filled in: %s:%d (%s)",
	      (ridx == 0) ? "callee" : "caller",
	      addr2char(sstosa(&packet->raddr)), port,
	      (sp->rtp == NULL) ? "RTP" : "RTCP");

	    /*
	     * Check if we have updated RTP while RTCP is still
	     * empty or contains address that differs from one we
	     * used when updating RTP. Try to guess RTCP if so,
	     * should be handy for non-NAT'ed clients, and some
	     * NATed as well.
	     */
	    if (sp->rtcp != NULL && (sp->rtcp->addr[ridx] == NULL ||
	      !ishostseq(sp->rtcp->addr[ridx], sstosa(&packet->raddr)))) {
		if (sp->rtcp->addr[ridx] == NULL) {
		    sp->rtcp->addr[ridx] = malloc(packet->rlen);
		    if (sp->rtcp->addr[ridx] == NULL) {
			sp->pcount[3]++;
			rtpp_log_write(RTPP_LOG_ERR, sp->log,
			  "can't allocate memory for remote address - "
			  "removing session");
			remove_session(cf, sp);
			/* Break, sp is invalid now */
			break;
		    }
		}
		memcpy(sp->rtcp->addr[ridx], &packet->raddr, packet->rlen);
		satosin(sp->rtcp->addr[ridx])->sin_port = htons(port + 1);
		/* Use guessed value as the only true one for asymmetric clients */
		sp->rtcp->canupdate[ridx] = NOT(sp->rtcp->asymmetric[ridx]);
		rtpp_log_write(RTPP_LOG_INFO, sp->log, "guessing RTCP port "
		  "for %s to be %d",
		  (ridx == 0) ? "callee" : "caller", port + 1);
	    }
	}

	if (sp->resizers[ridx].output_nsamples > 0)
	    rtp_resizer_enqueue(&sp->resizers[ridx], &packet);
	if (packet != NULL)
	    send_packet(cf, sp, ridx, packet);
    }

    if (packet != NULL)
	rtp_packet_free(packet);
}
Ejemplo n.º 27
0
static int
prepare_pkt_hdr_pcap(struct rtpp_session *sp, struct rtp_packet *packet,
  union pkt_hdr_pcap *hdrp, struct sockaddr *daddr, struct sockaddr *ldaddr,
  int ldport, int face)
{
    struct sockaddr *src_addr, *dst_addr;
    uint16_t src_port, dst_port;
    pcaprec_hdr_t *pcaprec_hdr;
    struct udpip *udpip;
    int pcap_size;

    if (packet->rtime == -1) {
	rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "can't get current time");
	return -1;
    }

    if (face == 0) {
        src_addr = sstosa(&(packet->raddr));
        src_port = satosin(src_addr)->sin_port;
        dst_addr = packet->laddr;
        dst_port = htons(packet->rport);
    } else {
        src_addr = ldaddr;
        src_port = htons(ldport);
        dst_addr = daddr;
        dst_port = satosin(dst_addr)->sin_port;
    }

    if (sstosa(src_addr)->sa_family != AF_INET) {
	rtpp_log_ewrite(RTPP_LOG_ERR, sp->log, "only AF_INET pcap format is supported");
	return -1;
    }

    memset(hdrp, 0, sizeof(*hdrp));

#if (PCAP_FORMAT == DLT_NULL)
    hdrp->null.family = sstosa(src_addr)->sa_family;
    pcaprec_hdr = &(hdrp->null.pcaprec_hdr);
    udpip = &(hdrp->null.udpip);
    pcap_size = sizeof(hdrp->null);
#else
    /* Prepare fake ethernet header */
    hdrp->en10t.ether_type = htons(0x800);
    memcpy(hdrp->en10t.ether_dhost + 2, &(satosin(dst_addr)->sin_addr), 4);
    memcpy(hdrp->en10t.ether_shost + 2, &(satosin(src_addr)->sin_addr), 4);
    pcaprec_hdr = &(hdrp->en10t.pcaprec_hdr);
    udpip = &(hdrp->en10t.udpip);
    pcap_size = sizeof(hdrp->en10t);
#endif

    dtime2ts(packet->rtime, &(pcaprec_hdr->ts_sec), &(pcaprec_hdr->ts_usec));
    pcaprec_hdr->orig_len = pcaprec_hdr->incl_len = pcap_size -
      sizeof(*pcaprec_hdr) + packet->size;

    /* Prepare fake IP header */
    udpip->iphdr.ip_v = 4;
    udpip->iphdr.ip_hl = sizeof(udpip->iphdr) >> 2;
    udpip->iphdr.ip_len = htons(sizeof(udpip->iphdr) + sizeof(udpip->udphdr) + packet->size);
    udpip->iphdr.ip_src = satosin(src_addr)->sin_addr;
    udpip->iphdr.ip_dst = satosin(dst_addr)->sin_addr;
    udpip->iphdr.ip_p = IPPROTO_UDP;
    udpip->iphdr.ip_id = htons(ip_id++);
    udpip->iphdr.ip_ttl = 127;
    udpip->iphdr.ip_sum = rtpp_in_cksum(&(udpip->iphdr), sizeof(udpip->iphdr));

    /* Prepare fake UDP header */
    udpip->udphdr.uh_sport = src_port;
    udpip->udphdr.uh_dport = dst_port;
    udpip->udphdr.uh_ulen = htons(sizeof(udpip->udphdr) + packet->size);

    return 0;
}
Ejemplo n.º 28
0
void dumppacket(FILE *fd, char *dir, struct sockaddr *sa, 
	char *cp, int size, struct timeval *stamp)
{
	struct rip *msg = (struct rip *)cp;
	struct sockaddr_in *who=(struct sockaddr_in *)sa;
	struct netinfo *n;

	if (fd == NULL)
		return;
	if (msg->rip_cmd && msg->rip_cmd < RIPCMD_MAX)
		fprintf(fd, "%s %s %s.%d %.19s:\n", ripcmds[msg->rip_cmd],
		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
		    ctime(&stamp->tv_sec));
	else {
		fprintf(fd, "Bad cmd 0x%x %s %s.%d %.19s\n", msg->rip_cmd,
		    dir, inet_ntoa(who->sin_addr), ntohs(who->sin_port),
		    ctime(&stamp->tv_sec));
		fprintf(fd, "size=%d cp=%p packet=%p\n", size, cp, packet);
		fflush(fd);
		return;
	}
	if (tracepackets && tracecontents == 0) {
		fflush(fd);
		return;
	}
	switch (msg->rip_cmd) {

	case RIPCMD_REQUEST:
	case RIPCMD_RESPONSE:
		size -= 4 * sizeof (char);
		n = msg->rip_nets;
		for (; size > 0; n++, size -= sizeof (struct netinfo)) {
			if (size < (int)sizeof (struct netinfo)) {
				fprintf(fd, "(truncated record, len %d)\n",
				    size);
				break;
			}
			if (sizeof(n->rip_dst.sa_family) > 1)
			    n->rip_dst.sa_family = ntohs(n->rip_dst.sa_family);

			switch ((int)n->rip_dst.sa_family) {

			case AF_INET:
				fprintf(fd, "\tdst %s metric %ld\n",
#define	satosin(sa)	((struct sockaddr_in *)&sa)
				     inet_ntoa(satosin(n->rip_dst)->sin_addr),
				     (long int)ntohl(n->rip_metric));
				break;

			default:
				fprintf(fd, "\taf %d? metric %ld\n",
				     n->rip_dst.sa_family,
				     (long int)ntohl(n->rip_metric));
				break;
			}
		}
		break;

	case RIPCMD_TRACEON:
		fprintf(fd, "\tfile=%*s\n", size, msg->rip_tracefile);
		break;

	case RIPCMD_TRACEOFF:
		break;
	}
	fflush(fd);
	if (ferror(fd))
		traceoff();
}
Ejemplo n.º 29
0
static void
vmt_tclo_tick(void *xarg)
{
	struct vmt_softc *sc = xarg;
	u_int32_t rlen;
	u_int16_t ack;

	/* reopen tclo channel if it's currently closed */
	if (sc->sc_tclo_rpc.channel == 0 &&
	    sc->sc_tclo_rpc.cookie1 == 0 &&
	    sc->sc_tclo_rpc.cookie2 == 0) {
		if (vm_rpc_open(&sc->sc_tclo_rpc, VM_RPC_OPEN_TCLO) != 0) {
			device_printf(sc->sc_dev, "unable to reopen TCLO channel\n");
			callout_schedule(&sc->sc_tclo_tick, hz * 15);
			return;
		}

		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_RESET_REPLY) != 0) {
			device_printf(sc->sc_dev, "failed to send reset reply\n");
			sc->sc_rpc_error = 1;
			goto out;
		} else {
			sc->sc_rpc_error = 0;
		}
	}

	if (sc->sc_tclo_ping) {
		if (vm_rpc_send(&sc->sc_tclo_rpc, NULL, 0) != 0) {
			device_printf(sc->sc_dev, "failed to send TCLO outgoing ping\n");
			sc->sc_rpc_error = 1;
			goto out;
		}
	}

	if (vm_rpc_get_length(&sc->sc_tclo_rpc, &rlen, &ack) != 0) {
		device_printf(sc->sc_dev, "failed to get length of incoming TCLO data\n");
		sc->sc_rpc_error = 1;
		goto out;
	}

	if (rlen == 0) {
		sc->sc_tclo_ping = 1;
		goto out;
	}

	if (rlen >= VMT_RPC_BUFLEN) {
		rlen = VMT_RPC_BUFLEN - 1;
	}
	if (vm_rpc_get_data(&sc->sc_tclo_rpc, sc->sc_rpc_buf, rlen, ack) != 0) {
		device_printf(sc->sc_dev, "failed to get incoming TCLO data\n");
		sc->sc_rpc_error = 1;
		goto out;
	}
	sc->sc_tclo_ping = 0;

#ifdef VMT_DEBUG
	printf("vmware: received message '%s'\n", sc->sc_rpc_buf);
#endif

	if (strcmp(sc->sc_rpc_buf, "reset") == 0) {

		if (sc->sc_rpc_error != 0) {
			device_printf(sc->sc_dev, "resetting rpc\n");
			vm_rpc_close(&sc->sc_tclo_rpc);
			/* reopen and send the reset reply next time around */
			goto out;
		}

		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_RESET_REPLY) != 0) {
			device_printf(sc->sc_dev, "failed to send reset reply\n");
			sc->sc_rpc_error = 1;
		}

	} else if (strcmp(sc->sc_rpc_buf, "ping") == 0) {

		vmt_update_guest_info(sc);
		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
			device_printf(sc->sc_dev, "error sending ping response\n");
			sc->sc_rpc_error = 1;
		}

	} else if (strcmp(sc->sc_rpc_buf, "OS_Halt") == 0) {
		vmt_do_shutdown(sc);
	} else if (strcmp(sc->sc_rpc_buf, "OS_Reboot") == 0) {
		vmt_do_reboot(sc);
	} else if (strcmp(sc->sc_rpc_buf, "OS_PowerOn") == 0) {
		vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_POWERON);
		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
			device_printf(sc->sc_dev, "error sending poweron response\n");
			sc->sc_rpc_error = 1;
		}
	} else if (strcmp(sc->sc_rpc_buf, "OS_Suspend") == 0) {
		log(LOG_KERN | LOG_NOTICE, "VMware guest entering suspended state\n");

		vmt_tclo_state_change_success(sc, 1, VM_STATE_CHANGE_SUSPEND);
		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
			device_printf(sc->sc_dev, "error sending suspend response\n");
			sc->sc_rpc_error = 1;
		}
	} else if (strcmp(sc->sc_rpc_buf, "OS_Resume") == 0) {
		vmt_do_resume(sc);
	} else if (strcmp(sc->sc_rpc_buf, "Capabilities_Register") == 0) {

		/* don't know if this is important at all */
		if (vm_rpc_send_rpci_tx(sc, "vmx.capability.unified_loop toolbox") != 0) {
			device_printf(sc->sc_dev, "unable to set unified loop\n");
			sc->sc_rpc_error = 1;
		}
		if (vm_rpci_response_successful(sc) == 0) {
			device_printf(sc->sc_dev, "host rejected unified loop setting\n");
		}

		/* the trailing space is apparently important here */
		if (vm_rpc_send_rpci_tx(sc, "tools.capability.statechange ") != 0) {
			device_printf(sc->sc_dev, "unable to send statechange capability\n");
			sc->sc_rpc_error = 1;
		}
		if (vm_rpci_response_successful(sc) == 0) {
			device_printf(sc->sc_dev, "host rejected statechange capability\n");
		}

		if (vm_rpc_send_rpci_tx(sc, "tools.set.version %u", VM_VERSION_UNMANAGED) != 0) {
			device_printf(sc->sc_dev, "unable to set tools version\n");
			sc->sc_rpc_error = 1;
		}

		vmt_update_guest_uptime(sc);

		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
			device_printf(sc->sc_dev, "error sending capabilities_register response\n");
			sc->sc_rpc_error = 1;
		}
	} else if (strcmp(sc->sc_rpc_buf, "Set_Option broadcastIP 1") == 0) {
		struct ifnet *iface;
		struct sockaddr_in *guest_ip;

		/* find first available ipv4 address */
		guest_ip = NULL;
		IFNET_FOREACH(iface) {
			struct ifaddr *iface_addr;

			/* skip loopback */
			if (strncmp(iface->if_xname, "lo", 2) == 0 &&
			    iface->if_xname[2] >= '0' && iface->if_xname[2] <= '9') {
				continue;
			}

			IFADDR_FOREACH(iface_addr, iface) {
				if (iface_addr->ifa_addr->sa_family != AF_INET) {
					continue;
				}

				guest_ip = satosin(iface_addr->ifa_addr);
				break;
			}
		}

		if (guest_ip != NULL) {
			if (vm_rpc_send_rpci_tx(sc, "info-set guestinfo.ip %s",
			    inet_ntoa(guest_ip->sin_addr)) != 0) {
				device_printf(sc->sc_dev, "unable to send guest IP address\n");
				sc->sc_rpc_error = 1;
			}

			if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_OK) != 0) {
				device_printf(sc->sc_dev, "error sending broadcastIP response\n");
				sc->sc_rpc_error = 1;
			}
		} else {
			if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_ERROR_IP_ADDR) != 0) {
				device_printf(sc->sc_dev,
				    "error sending broadcastIP error response\n");
				sc->sc_rpc_error = 1;
			}
		}
	} else {
		if (vm_rpc_send_str(&sc->sc_tclo_rpc, VM_RPC_REPLY_ERROR) != 0) {
Ejemplo n.º 30
0
int
prepare_rule(u_int32_t id, int rs_num, struct sockaddr *src,
    struct sockaddr *dst, u_int16_t d_port, u_int8_t proto)
{
	char an[PF_ANCHOR_NAME_SIZE];

	if ((src->sa_family != AF_INET && src->sa_family != AF_INET6) ||
	    (src->sa_family != dst->sa_family)) {
	    	errno = EPROTONOSUPPORT;
		return (-1);
	}

	memset(&pfp, 0, sizeof pfp);
	memset(&pfr, 0, sizeof pfr);
	snprintf(an, PF_ANCHOR_NAME_SIZE, "%s/%d.%d", FTP_PROXY_ANCHOR,
	    getpid(), id);
	strlcpy(pfp.anchor, an, PF_ANCHOR_NAME_SIZE);
	strlcpy(pfr.anchor, an, PF_ANCHOR_NAME_SIZE);

	switch (rs_num) {
	case PF_RULESET_FILTER:
		pfr.ticket = pfte[TRANS_FILTER].ticket;
		break;
	case PF_RULESET_NAT:
		pfr.ticket = pfte[TRANS_NAT].ticket;
		break;
	case PF_RULESET_RDR:
		pfr.ticket = pfte[TRANS_RDR].ticket;
		break;
	default:
		errno = EINVAL;
		return (-1);
	}
	if (ioctl(dev, DIOCBEGINADDRS, &pfp) == -1)
		return (-1);
	pfr.pool_ticket = pfp.ticket;

	/* Generic for all rule types. */
	pfr.rule.af = src->sa_family;
	pfr.rule.proto = proto;
	pfr.rule.src.addr.type = PF_ADDR_ADDRMASK;
	pfr.rule.dst.addr.type = PF_ADDR_ADDRMASK;
	if (src->sa_family == AF_INET) {
		memcpy(&pfr.rule.src.addr.v.a.addr.v4,
		    &satosin(src)->sin_addr.s_addr, 4);
		memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 4);
		memcpy(&pfr.rule.dst.addr.v.a.addr.v4,
		    &satosin(dst)->sin_addr.s_addr, 4);
		memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 4);
	} else {
		memcpy(&pfr.rule.src.addr.v.a.addr.v6,
		    &satosin6(src)->sin6_addr.s6_addr, 16);
		memset(&pfr.rule.src.addr.v.a.mask.addr8, 255, 16);
		memcpy(&pfr.rule.dst.addr.v.a.addr.v6,
		    &satosin6(dst)->sin6_addr.s6_addr, 16);
		memset(&pfr.rule.dst.addr.v.a.mask.addr8, 255, 16);
	}
	pfr.rule.dst.port_op = PF_OP_EQ;
	pfr.rule.dst.port[0] = htons(d_port);

	switch (rs_num) {
	case PF_RULESET_FILTER:
		/*
		 * pass quick [log] inet[6] proto tcp \
		 *     from $src to $dst port = $d_port flags S/SAFR keep state
		 *     (max 1) [queue qname]
		 */
		pfr.rule.action = PF_PASS;
		pfr.rule.quick = 1;
		pfr.rule.log = rule_log;
		pfr.rule.keep_state = 1;
#ifdef __FreeBSD__
		pfr.rule.flags = (proto == IPPROTO_TCP ? TH_SYN : 0);
		pfr.rule.flagset = (proto == IPPROTO_TCP ?
		    (TH_SYN|TH_ACK|TH_FIN|TH_RST) : 0);
#else
		pfr.rule.flags = (proto == IPPROTO_TCP ? TH_SYN : NULL);
		pfr.rule.flagset = (proto == IPPROTO_TCP ?
		    (TH_SYN|TH_ACK|TH_FIN|TH_RST) : NULL);
#endif
		pfr.rule.max_states = 1;
		if (qname != NULL)
			strlcpy(pfr.rule.qname, qname, sizeof pfr.rule.qname);
		break;
	case PF_RULESET_NAT:
		/*
		 * nat inet[6] proto tcp from $src to $dst port $d_port -> $nat
		 */
		pfr.rule.action = PF_NAT;
		break;
	case PF_RULESET_RDR:
		/*
		 * rdr inet[6] proto tcp from $src to $dst port $d_port -> $rdr
		 */
		pfr.rule.action = PF_RDR;
		break;
	default:
		errno = EINVAL;
		return (-1);
	}

	return (0);
}