/* associated socket ceases to exist */ static void pep_sock_close(struct sock *sk, long timeout) { struct pep_sock *pn = pep_sk(sk); int ifindex = 0; sock_hold(sk); /* keep a reference after sk_common_release() */ sk_common_release(sk); lock_sock(sk); if (sk->sk_state == TCP_LISTEN) { /* Destroy the listen queue */ struct sock *sknode; struct hlist_node *p, *n; sk_for_each_safe(sknode, p, n, &pn->ackq) sk_del_node_init(sknode); sk->sk_state = TCP_CLOSE; } ifindex = pn->ifindex; pn->ifindex = 0; release_sock(sk); if (ifindex) gprs_detach(sk); sock_put(sk); }
/* associated socket ceases to exist */ static void pep_sock_close(struct sock *sk, long timeout) { struct pep_sock *pn = pep_sk(sk); int ifindex = 0; sock_hold(sk); /* keep a reference after sk_common_release() */ sk_common_release(sk); lock_sock(sk); if ((1 << sk->sk_state) & (TCPF_SYN_RECV|TCPF_ESTABLISHED)) { if (sk->sk_backlog_rcv == pipe_do_rcv) /* Forcefully remove dangling Phonet pipe */ pipe_do_remove(sk); else pipe_handler_request(sk, PNS_PEP_DISCONNECT_REQ, PAD, NULL, 0); } sk->sk_state = TCP_CLOSE; ifindex = pn->ifindex; pn->ifindex = 0; release_sock(sk); if (ifindex) gprs_detach(sk); sock_put(sk); }
static void raw_close(struct sock *sk, long timeout) { /* * Raw sockets may have direct kernel references. Kill them. */ ip_ra_control(sk, 0, NULL); sk_common_release(sk); }
static int serval_inet_connect(struct socket *sock, struct sockaddr *addr, int alen, int flags) { struct sockaddr_in *in = (struct sockaddr_in *)addr; struct sockaddr_sv sv; unsigned char localhost[4] = { 0x7f, 0x0, 0x0, 0x1 }; struct sock *sk = sock->sk; if (alen < sizeof(addr->sa_family)) return -EINVAL; if (addr->sa_family != AF_INET) return -EAFNOSUPPORT; if (memcmp(&in->sin_addr, &localhost, sizeof(in->sin_addr)) == 0) { /* Give back control to legacy TCP in case of localhost */ LOG_DBG("Dest is localhost, giving back sock\n"); sock->ops = &inet_stream_ops; sock->sk = serval_sk(sk)->old_sk; module_put(serval_inet_stream_ops.owner); sk_common_release(sk); sk = sock->sk; sock_put(sk); sk->sk_type = sock->type; sk->sk_wq = sock->wq; return inet_stream_ops.connect(sock, addr, alen, flags); } /* Release old TCP sock */ module_put(inet_stream_ops.owner); sock_put(serval_sk(sk)->old_sk); sk_common_release(serval_sk(sk)->old_sk); serval_sk(sk)->old_sk = NULL; inet_addr_to_service(in, &sv); alen = sizeof(sv); return serval_stream_ops.connect(sock, (struct sockaddr *)&sv, alen, flags); }
/* * Create a socket. Initialise the socket, blank the addresses * set the state. */ static int ieee802154_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; int rc; struct proto *proto; const struct proto_ops *ops; if (net != &init_net) return -EAFNOSUPPORT; switch (sock->type) { case SOCK_RAW: proto = &ieee802154_raw_prot; ops = &ieee802154_raw_ops; break; case SOCK_DGRAM: proto = &ieee802154_dgram_prot; ops = &ieee802154_dgram_ops; break; default: rc = -ESOCKTNOSUPPORT; goto out; } rc = -ENOMEM; sk = sk_alloc(net, PF_IEEE802154, GFP_KERNEL, proto); if (!sk) goto out; rc = 0; sock->ops = ops; sock_init_data(sock, sk); /* FIXME: sk->sk_destruct */ sk->sk_family = PF_IEEE802154; /* Checksums on by default */ sock_set_flag(sk, SOCK_ZAPPED); if (sk->sk_prot->hash) sk->sk_prot->hash(sk); if (sk->sk_prot->init) { rc = sk->sk_prot->init(sk); if (rc) sk_common_release(sk); } out: return rc; }
/* associated socket ceases to exist */ static void pn_sock_close(struct sock *sk, long timeout) { sk_common_release(sk); }
static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, size_t len) { struct inet_sock *inet = inet_sk(sk); struct ipcm_cookie ipc; struct rtable *rt = NULL; int free = 0; __be32 daddr; __be32 saddr; u8 tos; int err; err = -EMSGSIZE; if (len > 0xFFFF) goto out; /* * Check the flags. */ err = -EOPNOTSUPP; if (msg->msg_flags & MSG_OOB) /* Mirror BSD error message */ goto out; /* compatibility */ /* * Get and verify the address. */ if (msg->msg_namelen) { struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name; err = -EINVAL; if (msg->msg_namelen < sizeof(*usin)) goto out; if (usin->sin_family != AF_INET) { static int complained; if (!complained++) printk(KERN_INFO "%s forgot to set AF_INET in " "raw sendmsg. Fix it!\n", current->comm); err = -EAFNOSUPPORT; if (usin->sin_family) goto out; } daddr = usin->sin_addr.s_addr; /* ANK: I did not forget to get protocol from port field. * I just do not know, who uses this weirdness. * IP_HDRINCL is much more convenient. */ } else { err = -EDESTADDRREQ; if (sk->sk_state != TCP_ESTABLISHED) goto out; daddr = inet->inet_daddr; } ipc.addr = inet->inet_saddr; ipc.opt = NULL; ipc.tx_flags = 0; ipc.oif = sk->sk_bound_dev_if; if (msg->msg_controllen) { err = ip_cmsg_send(sock_net(sk), msg, &ipc); if (err) goto out; if (ipc.opt) free = 1; } saddr = ipc.addr; ipc.addr = daddr; if (!ipc.opt) ipc.opt = inet->opt; if (ipc.opt) { err = -EINVAL; /* Linux does not mangle headers on raw sockets, * so that IP options + IP_HDRINCL is non-sense. */ if (inet->hdrincl) goto done; if (ipc.opt->srr) { if (!daddr) goto done; daddr = ipc.opt->faddr; } } tos = RT_CONN_FLAGS(sk); if (msg->msg_flags & MSG_DONTROUTE) tos |= RTO_ONLINK; if (ipv4_is_multicast(daddr)) { if (!ipc.oif) ipc.oif = inet->mc_index; if (!saddr) saddr = inet->mc_addr; } { struct flowi4 fl4 = { .flowi4_oif = ipc.oif, .flowi4_mark = sk->sk_mark, .daddr = daddr, .saddr = saddr, .flowi4_tos = tos, .flowi4_proto = (inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol), .flowi4_flags = FLOWI_FLAG_CAN_SLEEP, }; if (!inet->hdrincl) { err = raw_probe_proto_opt(&fl4, msg); if (err) goto done; } security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); rt = ip_route_output_flow(sock_net(sk), &fl4, sk); if (IS_ERR(rt)) { err = PTR_ERR(rt); rt = NULL; goto done; } } err = -EACCES; if (rt->rt_flags & RTCF_BROADCAST && !sock_flag(sk, SOCK_BROADCAST)) goto done; if (msg->msg_flags & MSG_CONFIRM) goto do_confirm; back_from_confirm: if (inet->hdrincl) err = raw_send_hdrinc(sk, msg->msg_iov, len, &rt, msg->msg_flags); else { if (!ipc.addr) ipc.addr = rt->rt_dst; lock_sock(sk); err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0, &ipc, &rt, msg->msg_flags); if (err) ip_flush_pending_frames(sk); else if (!(msg->msg_flags & MSG_MORE)) { err = ip_push_pending_frames(sk); if (err == -ENOBUFS && !inet->recverr) err = 0; } release_sock(sk); } done: if (free) kfree(ipc.opt); ip_rt_put(rt); out: if (err < 0) return err; return len; do_confirm: dst_confirm(&rt->dst); if (!(msg->msg_flags & MSG_PROBE) || len) goto back_from_confirm; err = 0; goto done; } static void raw_close(struct sock *sk, long timeout) { /* * Raw sockets may have direct kernel refereneces. Kill them. */ ip_ra_control(sk, 0, NULL); sk_common_release(sk); }
static void raw_close(struct sock *sk, long timeout) { ip_ra_control(sk, 0, NULL); sk_common_release(sk); }
int mhost_create(struct net *net, struct socket *sock, int protocol, int kern) { struct sock *sk; struct inet_sock *inet; struct ipv6_pinfo *np; struct inet_protosw *answer; int err; char answer_no_check; struct proto *answer_prot; unsigned char answer_flags; printk(KERN_INFO "mhost_create called\n"); sock->state = SS_UNCONNECTED; /* we only support SOCK_DGRAM as of now... */ answer = &mhost_dgram_protosw; protocol = IPPROTO_UDP; /* end "big answer/protocol code mess" here */ err = -EPERM; if (sock->type == SOCK_RAW && !capable(CAP_NET_RAW)) goto out; sock->ops = answer->ops; answer_prot = answer->prot; answer_no_check = answer->no_check; answer_flags = answer->flags; WARN_ON(answer_prot->slab == NULL); err = -ENOBUFS, sk = sk_alloc(net, AF_MHOST, GFP_KERNEL, answer_prot); if (sk == NULL) goto out; sock_init_data(sock, sk); err = 0; sk->sk_no_check = answer_no_check; if (INET_PROTOSW_REUSE & answer_flags) sk->sk_reuse = 1; inet = inet_sk(sk); inet->is_icsk = (INET_PROTOSW_ICSK & answer_flags) != 0; if (SOCK_RAW == sock->type) { inet->inet_num = protocol; if (IPPROTO_RAW == protocol) inet->hdrincl = 1; } sk->sk_destruct = inet_sock_destruct; sk->sk_protocol = protocol; sk->sk_family = AF_INET6; /* HACK FOR RECEIVING UDP6!!! */ sk->sk_backlog_rcv = sk->sk_prot->backlog_rcv; inet_sk(sk)->pinet6 = np = (struct ipv6_pinfo *) mhost_sk_generic(sk); /* HERE DO ALL MHOST-SPECIFIC INITS!!! */ /* now backwards-compat for IPv6 */ np->hop_limit = -1; np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; np->mc_loop = 1; np->pmtudisc = IPV6_PMTUDISC_WANT; np->ipv6only = net->ipv6.sysctl.bindv6only; /* now backwards-compat for IPv4 */ inet->uc_ttl = -1; inet->mc_loop = 1; inet->mc_ttl = 1; inet->mc_index = 0; inet->mc_list = NULL; sock_init_data(sock, sk); inet->uc_ttl = -1; inet->mc_loop = 1; inet->mc_ttl = 1; inet->mc_all = 1; inet->mc_index = 0; inet->mc_list = NULL; if (ipv4_config.no_pmtu_disc) inet->pmtudisc = IP_PMTUDISC_DONT; else inet->pmtudisc = IP_PMTUDISC_WANT; sk_refcnt_debug_inc(sk); if (inet->inet_num) { /* assumes that any protocol which allows * the user to assign a number at socket * creation time automatically shares. */ inet->inet_sport = htons(inet->inet_num); sk->sk_prot->hash(sk); } if (sk->sk_prot->init) { int err = sk->sk_prot->init(sk); if (err) sk_common_release(sk); } out: return err; };
static int serval_inet_tcp_init_sock(struct sock *sk) { struct socket *sock = sk->sk_socket; struct sock *old_sk = sk; const struct proto_ops *old_ops = sock->ops; struct inet_sock *inet; int err = 0; LOG_DBG("init sock\n"); /* First fully initialize the old sock. Otherwise, the release function will fail. */ err = old_tcp_prot.init(sk); if (err) return err; sock->ops = &serval_inet_stream_ops; sk = serval_sk_alloc(sock_net(sk), sock, GFP_KERNEL, SERVAL_PROTO_TCP, &serval_tcp_proto); if (!sk) { LOG_ERR("Fail alloc\n"); goto out_fail_alloc; } /* Initialize serval sock part of socket */ serval_sock_init(sk); /* Initialize inet part */ inet = inet_sk(sk); inet->uc_ttl = -1; /* Let IP decide TTL */ inet->mc_loop = 1; inet->mc_ttl = 1; inet->mc_index = 0; inet->mc_list = NULL; if (sk->sk_prot->init) { /* Call protocol specific init */ err = sk->sk_prot->init(sk); if (err < 0) { LOG_ERR("Fail init\n"); goto out_fail_init; } } sock_hold(old_sk); serval_sk(sk)->old_sk = old_sk; LOG_DBG("Successfully hijacked sock\n"); return 0; out_fail_init: sk_common_release(sk); out_fail_alloc: sock->ops = old_ops; sock->sk = old_sk; return 0; }