1/* $NetBSD: svr4_net.c,v 1.57 2009/12/09 21:32:58 dsl Exp $ */ 2 3/*- 4 * Copyright (c) 1994, 2008, 2009 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Christos Zoulas. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 32/* 33 * Emulate /dev/{udp,tcp,...} 34 */ 35 36#include <sys/cdefs.h> 37__KERNEL_RCSID(0, "$NetBSD: svr4_net.c,v 1.57 2009/12/09 21:32:58 dsl Exp $"); 38 39#define COMPAT_SVR4 1 40 41#include <sys/param.h> 42#include <sys/kernel.h> 43#include <sys/systm.h> 44#include <sys/buf.h> 45#include <sys/malloc.h> 46#include <sys/ioctl.h> 47#include <sys/tty.h> 48#include <sys/file.h> 49#include <sys/filedesc.h> 50#include <sys/fcntl.h> 51#include <sys/select.h> 52#include <sys/socket.h> 53#include <sys/socketvar.h> 54#include <sys/protosw.h> 55#include <sys/domain.h> 56#include <net/if.h> 57#include <netinet/in.h> 58#include <sys/proc.h> 59#include <sys/vnode.h> 60#include <sys/device.h> 61#include <sys/conf.h> 62#include <sys/mount.h> 63 64#include <sys/syscallargs.h> 65 66#include <compat/svr4/svr4_types.h> 67#include <compat/svr4/svr4_util.h> 68#include <compat/svr4/svr4_signal.h> 69#include <compat/svr4/svr4_lwp.h> 70#include <compat/svr4/svr4_ucontext.h> 71#include <compat/svr4/svr4_syscallargs.h> 72#include <compat/svr4/svr4_ioctl.h> 73#include <compat/svr4/svr4_stropts.h> 74#include <compat/svr4/svr4_socket.h> 75 76dev_type_open(svr4_netopen); 77 78const struct cdevsw svr4_net_cdevsw = { 79 svr4_netopen, noclose, noread, nowrite, noioctl, 80 nostop, notty, nopoll, nommap, nokqfilter, D_OTHER, 81}; 82 83/* 84 * Device minor numbers 85 */ 86enum { 87 dev_arp = 26, 88 dev_icmp = 27, 89 dev_ip = 28, 90 dev_tcp = 35, 91 dev_udp = 36, 92 dev_rawip = 37, 93 dev_unix_dgram = 38, 94 dev_unix_stream = 39, 95 dev_unix_ord_stream = 40 96}; 97 98int svr4_netattach(int); 99 100int svr4_soo_close(file_t *); 101 102static const struct fileops svr4_netops = { 103 .fo_read = soo_read, 104 .fo_write = soo_write, 105 .fo_ioctl = soo_ioctl, 106 .fo_fcntl = soo_fcntl, 107 .fo_poll = soo_poll, 108 .fo_stat = soo_stat, 109 .fo_close = svr4_soo_close, 110 .fo_kqfilter = soo_kqfilter, 111 .fo_restart = soo_restart, 112}; 113 114 115/* 116 * Used by new config, but we don't need it. 117 */ 118int 119svr4_netattach(int n) 120{ 121 return 0; 122} 123 124 125int 126svr4_netopen(dev_t dev, int flag, int mode, struct lwp *l) 127{ 128 int type, protocol; 129 int fd; 130 file_t *fp; 131 struct socket *so; 132 int error; 133 int family; 134 135 DPRINTF(("netopen(")); 136 137 if (curlwp->l_dupfd >= 0) /* XXX */ 138 return ENODEV; 139 140 switch (minor(dev)) { 141 case dev_udp: 142 family = AF_INET; 143 type = SOCK_DGRAM; 144 protocol = IPPROTO_UDP; 145 DPRINTF(("udp, ")); 146 break; 147 148 case dev_tcp: 149 family = AF_INET; 150 type = SOCK_STREAM; 151 protocol = IPPROTO_TCP; 152 DPRINTF(("tcp, ")); 153 break; 154 155 case dev_ip: 156 case dev_rawip: 157 family = AF_INET; 158 type = SOCK_RAW; 159 protocol = IPPROTO_IP; 160 DPRINTF(("ip, ")); 161 break; 162 163 case dev_icmp: 164 family = AF_INET; 165 type = SOCK_RAW; 166 protocol = IPPROTO_ICMP; 167 DPRINTF(("icmp, ")); 168 break; 169 170 case dev_unix_dgram: 171 family = AF_LOCAL; 172 type = SOCK_DGRAM; 173 protocol = 0; 174 DPRINTF(("unix-dgram, ")); 175 break; 176 177 case dev_unix_stream: 178 case dev_unix_ord_stream: 179 family = AF_LOCAL; 180 type = SOCK_STREAM; 181 protocol = 0; 182 DPRINTF(("unix-stream, ")); 183 break; 184 185 default: 186 DPRINTF(("%"PRId32");\n", minor(dev))); 187 return EOPNOTSUPP; 188 } 189 190 if ((error = fd_allocfile(&fp, &fd)) != 0) 191 return error; 192 193 if ((error = socreate(family, &so, type, protocol, l, NULL)) != 0) { 194 DPRINTF(("socreate error %d\n", error)); 195 fd_abort(curproc, fp, fd); 196 return error; 197 } 198 199 error = fd_clone(fp, fd, flag, &svr4_netops, so); 200 fp->f_type = DTYPE_SOCKET; 201 (void)svr4_stream_get(fp); 202 203 DPRINTF(("ok);\n")); 204 return error; 205} 206 207 208int 209svr4_soo_close(file_t *fp) 210{ 211 struct socket *so = fp->f_data; 212 213 svr4_delete_socket(curproc, fp); 214 free(so->so_internal, M_NETADDR); 215 return soo_close(fp); 216} 217 218 219struct svr4_strm * 220svr4_stream_get(file_t *fp) 221{ 222 struct socket *so; 223 struct svr4_strm *st; 224 225 if (fp == NULL || fp->f_type != DTYPE_SOCKET) 226 return NULL; 227 228 so = fp->f_data; 229 230 if (so->so_internal) 231 return so->so_internal; 232 233 /* Allocate a new one. */ 234 fp->f_ops = &svr4_netops; 235 st = malloc(sizeof(struct svr4_strm), M_NETADDR, M_WAITOK); 236 st->s_family = so->so_proto->pr_domain->dom_family; 237 st->s_cmd = ~0; 238 st->s_afd = -1; 239 st->s_eventmask = 0; 240 so->so_internal = st; 241 242 return st; 243} 244