Пример #1
0
static int
send_attach(struct socket *so, int proto, struct thread *td)
{
	int error;

	SEND_LOCK();
	if (V_send_so != NULL) {
		SEND_UNLOCK();
		return (EEXIST);
	}

	error = priv_check(td, PRIV_NETINET_RAW);
	if (error) {
		SEND_UNLOCK();
		return(error);
	}

	if (proto != IPPROTO_SEND) {
		SEND_UNLOCK();
		return (EPROTONOSUPPORT);
	}
	error = soreserve(so, send_sendspace, send_recvspace);
	if (error) {
		SEND_UNLOCK();
		return(error);
	}

	V_send_so = so;
	SEND_UNLOCK();

	return (0);
}
Пример #2
0
static void
send_close(struct socket *so)
{

	SEND_LOCK();
	if (V_send_so)
		V_send_so = NULL;
	SEND_UNLOCK();
}
Пример #3
0
static int
send_modevent(module_t mod, int type, void *unused)
{
#ifdef __notyet__
	VNET_ITERATOR_DECL(vnet_iter);
#endif
	int error;

	switch (type) {
	case MOD_LOAD:
		SEND_LOCK_INIT();

		error = pf_proto_register(PF_INET6, &send_protosw);
		if (error != 0) {
			printf("%s:%d: MOD_LOAD pf_proto_register(): %d\n",
			   __func__, __LINE__, error);
			SEND_LOCK_DESTROY();
			break;
		}
		send_sendso_input_hook = send_input;
		break;
	case MOD_UNLOAD:
		/* Do not allow unloading w/o locking. */
		return (EBUSY);
#ifdef __notyet__
		VNET_LIST_RLOCK_NOSLEEP();
		SEND_LOCK();
		VNET_FOREACH(vnet_iter) {
			CURVNET_SET(vnet_iter);
			if (V_send_so != NULL) {
				CURVNET_RESTORE();
				SEND_UNLOCK();
				VNET_LIST_RUNLOCK_NOSLEEP();
				return (EBUSY);
			}
			CURVNET_RESTORE();
		}
		SEND_UNLOCK();
		VNET_LIST_RUNLOCK_NOSLEEP();
		error = pf_proto_unregister(PF_INET6, IPPROTO_SEND, SOCK_RAW);
		if (error == 0)
			SEND_LOCK_DESTROY();
		send_sendso_input_hook = NULL;
		break;
#endif
	default:
		error = 0;
		break;
	}

	return (error);
}
Пример #4
0
/*
 * Send a SeND message to user space, that was either received and has to be
 * validated or was about to be send out and has to be handled by the SEND
 * daemon adding SeND ICMPv6 options.
 */
static int
send_input(struct mbuf *m, struct ifnet *ifp, int direction, int msglen __unused)
{
	struct ip6_hdr *ip6;
	struct sockaddr_send sendsrc;

	SEND_LOCK();
	if (V_send_so == NULL) {
		SEND_UNLOCK();
		return (-1);
	}

	/*
	 * Make sure to clear any possible internally embedded scope before
	 * passing the packet to user space for SeND cryptographic signature
	 * validation to succeed.
	 */
	ip6 = mtod(m, struct ip6_hdr *);
	in6_clearscope(&ip6->ip6_src);
	in6_clearscope(&ip6->ip6_dst);

	bzero(&sendsrc, sizeof(sendsrc));
	sendsrc.send_len = sizeof(sendsrc);
	sendsrc.send_family = AF_INET6;
	sendsrc.send_direction = direction;
	sendsrc.send_ifidx = ifp->if_index;

	/*
	 * Send incoming or outgoing traffic to user space either to be
	 * protected (outgoing) or validated (incoming) according to rfc3971.
	 */
	SOCKBUF_LOCK(&V_send_so->so_rcv);
	if (sbappendaddr_locked(&V_send_so->so_rcv,
	    (struct sockaddr *)&sendsrc, m, NULL) == 0) {
		SOCKBUF_UNLOCK(&V_send_so->so_rcv);
		/* XXX stats. */
		m_freem(m);
	} else {
		sorwakeup_locked(V_send_so);
	}

	SEND_UNLOCK();
	return (0);
}
Пример #5
0
/*
 *  cas_send_bs_msg()
 *
 *  (channel access server send message)
 */
void cas_send_bs_msg ( struct client *pclient, int lock_needed )
{
    int status;

    if ( CASDEBUG > 2 && pclient->send.stk ) {
        errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk );
    }

    if ( pclient->disconnect ) {
        if ( CASDEBUG > 2 ) {
            errlogPrintf ( "CAS: msg Discard for sock %d addr %x\n",
                pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr );
        }
        pclient->send.stk = 0u;
        return;
    }

    if ( lock_needed ) {
        SEND_LOCK ( pclient );
    }

    while ( pclient->send.stk && ! pclient->disconnect ) {
        status = send ( pclient->sock, pclient->send.buf, pclient->send.stk, 0 );
        if ( status >= 0 ) {
            unsigned transferSize = (unsigned) status;
            if ( transferSize >= pclient->send.stk ) {
                pclient->send.stk = 0;
                epicsTimeGetCurrent ( &pclient->time_at_last_send );
                break;
            }
            else {
                unsigned bytesLeft = pclient->send.stk - transferSize;
                memmove ( pclient->send.buf, &pclient->send.buf[transferSize], 
                    bytesLeft );
                pclient->send.stk = bytesLeft;
            }
        }
        else {
            int causeWasSocketHangup = 0;
            int anerrno = SOCKERRNO;
            char buf[64];

            if ( pclient->disconnect ) {
                pclient->send.stk = 0u;
                break;
            }

            if ( anerrno == SOCK_EINTR ) {
                continue;
            }

            if ( anerrno == SOCK_ENOBUFS ) {
                errlogPrintf (
                    "CAS: Out of network buffers, retrying send in 15 seconds\n" );
                epicsThreadSleep ( 15.0 );
                continue;
            }

            ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) );

            if (    
                anerrno == SOCK_ECONNABORTED ||
                anerrno == SOCK_ECONNRESET ||
                anerrno == SOCK_EPIPE ||
                anerrno == SOCK_ETIMEDOUT ) {
                causeWasSocketHangup = 1;
            }
            else {
                char sockErrBuf[64];
                epicsSocketConvertErrnoToString ( 
                    sockErrBuf, sizeof ( sockErrBuf ) );
                errlogPrintf ( "CAS: TCP send to %s failed - %s\n",
                    buf, sockErrBuf);
            }
            pclient->disconnect = TRUE;
            pclient->send.stk = 0u;

            /*
             * wakeup the receive thread
             */
            if ( ! causeWasSocketHangup ) {
                enum epicsSocketSystemCallInterruptMechanismQueryInfo info  =
                    epicsSocketSystemCallInterruptMechanismQuery ();
                switch ( info ) {
                case esscimqi_socketCloseRequired:
                    if ( pclient->sock != INVALID_SOCKET ) {
                        epicsSocketDestroy ( pclient->sock );
                        pclient->sock = INVALID_SOCKET;
                    }
                    break;
                case esscimqi_socketBothShutdownRequired:
                    {
                        int status = shutdown ( pclient->sock, SHUT_RDWR );
                        if ( status ) {
                            char sockErrBuf[64];
                            epicsSocketConvertErrnoToString ( 
                                sockErrBuf, sizeof ( sockErrBuf ) );
                            errlogPrintf ("CAS: Socket shutdown error - %s\n", 
                                sockErrBuf );
                        }
                    }
                    break;
                case esscimqi_socketSigAlarmRequired:
                    epicsSignalRaiseSigAlarm ( pclient->tid );
                    break;
                default:
                    break;
                };
                break;
            }
        }
    }

    if ( lock_needed ) {
        SEND_UNLOCK(pclient);
    }

    DLOG ( 3, ( "------------------------------\n\n" ) );

    return;
}
Пример #6
0
/*
 *  cas_send_dg_msg()
 *
 *  (channel access server send udp message)
 */
void cas_send_dg_msg ( struct client * pclient )
{
    int status;
    int sizeDG;
    char * pDG; 
    caHdr * pMsg;

    if ( CASDEBUG > 2 && pclient->send.stk ) {
        errlogPrintf ( "CAS: Sending a udp message of %d bytes\n", pclient->send.stk );
    }

    SEND_LOCK ( pclient );

    if ( pclient->send.stk <= sizeof (caHdr) ) {
        SEND_UNLOCK(pclient);
        return;
    }

    pDG = pclient->send.buf;
    pMsg = ( caHdr * ) pDG;
    sizeDG = pclient->send.stk;
    assert ( ntohs ( pMsg->m_cmmd ) == CA_PROTO_VERSION );
    if ( CA_V411 ( pclient->minor_version_number ) ) {
        pMsg->m_cid = htonl ( pclient->seqNoOfReq );
        pMsg->m_dataType = htons ( sequenceNoIsValid );
    }
    else {
        pDG += sizeof (caHdr);
        sizeDG -= sizeof (caHdr);
    }

    status = sendto ( pclient->sock, pDG, sizeDG, 0,
       (struct sockaddr *)&pclient->addr, sizeof(pclient->addr) );
    if ( status >= 0 ) {
        if ( status >= sizeDG ) {
            epicsTimeGetCurrent ( &pclient->time_at_last_send );
        }
        else {
            errlogPrintf ( 
                "CAS: System failed to send entire udp frame?\n" );
        }
    }
    else {
        char sockErrBuf[64];
        char buf[128];
        epicsSocketConvertErrnoToString ( 
            sockErrBuf, sizeof ( sockErrBuf ) );
        ipAddrToDottedIP ( &pclient->addr, buf, sizeof(buf) );
        errlogPrintf( "CAS: UDP send to %s failed - %s\n",
            buf, sockErrBuf);
    }

    pclient->send.stk = 0u;

    /*
     * add placeholder for the first version message should it be needed
     */
    rsrv_version_reply ( pclient );

    SEND_UNLOCK(pclient);

    DLOG ( 3, ( "------------------------------\n\n" ) );

    return;
}