merge unlink variants
[trinity.git] / syscalls / socket.c
blob23eff83cd090fc5df1cef43684fd3dd655c4bae3
1 /*
2 * SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol)
3 */
4 #include <stdlib.h>
5 #include <sys/types.h>
6 #include <sys/socket.h>
7 #include "compat.h"
8 #include "log.h"
9 #include "net.h"
10 #include "random.h"
11 #include "sanitise.h"
12 #include "shm.h"
13 #include "config.h"
14 #include "params.h"
15 #include "protocols.h"
16 #include "utils.h"
18 struct socket_ptr {
19 unsigned int family;
20 void (*func)(struct socket_triplet *st);
22 static const struct socket_ptr socketptrs[] = {
23 { .family = AF_APPLETALK, .func = &atalk_rand_socket },
24 { .family = AF_AX25, .func = &ax25_rand_socket },
25 #ifdef USE_CAIF
26 { .family = AF_CAIF, .func = &caif_rand_socket },
27 #endif
28 { .family = AF_CAN, .func = &can_rand_socket },
29 { .family = AF_DECnet, .func = &decnet_rand_socket },
30 { .family = AF_INET, .func = &inet_rand_socket },
31 { .family = AF_INET6, .func = &inet6_rand_socket },
32 { .family = AF_IPX, .func = &ipx_rand_socket },
33 { .family = AF_IRDA, .func = &irda_rand_socket },
34 { .family = AF_LLC, .func = &llc_rand_socket },
35 { .family = AF_NETLINK, .func = &netlink_rand_socket },
36 { .family = AF_NFC, .func = &nfc_rand_socket },
37 //TODO { .family = AF_IB, .func = &ib_rand_socket },
38 { .family = AF_PACKET, .func = &packet_rand_socket },
39 { .family = AF_PHONET, .func = &phonet_rand_socket },
40 { .family = AF_RDS, .func = &rds_rand_socket },
41 { .family = AF_TIPC, .func = &tipc_rand_socket },
42 { .family = AF_UNIX, .func = &unix_rand_socket },
43 { .family = AF_X25, .func = &x25_rand_socket },
46 void rand_proto_type(struct socket_triplet *st)
48 int n;
51 * One special moment on packet sockets. They
52 * can be created with SOCK_PACKET, so if
53 * PF_PACKET is disabled, choose some other type.
56 st->protocol = rand() % PROTO_MAX;
58 if (st->family == PF_INET && no_protos[PF_PACKET])
59 n = 5;
60 else
61 n = 6;
63 switch (rand() % n) {
64 case 0: st->type = SOCK_DGRAM; break;
65 case 1: st->type = SOCK_STREAM; break;
66 case 2: st->type = SOCK_SEQPACKET; break;
67 case 3: st->type = SOCK_RAW; break;
68 case 4: st->type = SOCK_RDM; break;
70 * Make sure it's last one.
72 case 5: st->type = SOCK_PACKET; break;
73 default: break;
77 /* note: also called from generate_sockets() */
78 int sanitise_socket_triplet(struct socket_triplet *st)
80 unsigned int i;
81 for (i = 0; i < ARRAY_SIZE(socketptrs); i++) {
82 if (socketptrs[i].family == st->family) {
83 socketptrs[i].func(st);
84 return 0;
88 /* Couldn't find func, fall back to random. */
89 return -1;
92 /* note: also called from sanitise_socketcall() */
93 void gen_socket_args(struct socket_triplet *st)
95 if (do_specific_proto == TRUE)
96 st->family = specific_proto;
98 else {
99 st->family = rand() % TRINITY_PF_MAX;
102 * If we get a disabled family, try to find
103 * first next allowed.
105 BUG_ON(st->family >= ARRAY_SIZE(no_protos));
106 if (no_protos[st->family]) {
107 st->family = find_next_enabled_proto(st->family);
108 if (st->family == -1u) {
109 outputerr("No available socket family found\n");
110 exit(EXIT_FAILURE);
115 /* sometimes, still gen rand crap */
116 if ((rand() % 100) == 0) {
117 rand_proto_type(st);
118 goto done;
121 /* otherwise.. sanitise based on the family. */
122 if (sanitise_socket_triplet(st) < 0)
123 rand_proto_type(st); /* Couldn't find func, fall back to random. */
126 done:
127 if ((rand() % 100) < 25)
128 st->type |= SOCK_CLOEXEC;
129 if ((rand() % 100) < 25)
130 st->type |= SOCK_NONBLOCK;
134 static void sanitise_socket(int childno)
136 struct socket_triplet st = { .family = 0, .type = 0, .protocol = 0 };
138 gen_socket_args(&st);
140 shm->a1[childno] = st.family;
141 shm->a2[childno] = st.type;
142 shm->a3[childno] = st.protocol;
145 struct syscallentry syscall_socket = {
146 .name = "socket",
147 .num_args = 3,
148 .arg1name = "family",
149 .arg2name = "type",
150 .arg3name = "protocol",
151 .sanitise = sanitise_socket,