
#include "queso.h"

/***************************************************************************/
/*
** This function retrieves the
** interface a ip will use.
** It also sets up the ip of
** the interface.
**/

LONG ASM
ip2if(REG(a0) struct global *g)
{
    register char                   buf[1024];
    struct ifreq                    ifr;
    register struct rt_msghdr       *rtm;
    register struct sockaddr_in     *sin;
    register void                   *pid;
    register LONG                   res;
    register int                    sr, sd = -1, seq;
    register char                   c;

    /* two sockets needed: 1 ROUTE/RAW and 1 INET/DGRAM */
    if (((sr = socket(AF_ROUTE,SOCK_RAW,0))<0) ||
        ((sd = socket(AF_INET,SOCK_DGRAM,0))<0))
    {
        res = ERR_NoSocket;
        goto end;
    }

    /* set rt_msghdr */
    rtm = (struct rt_msghdr *)buf;
    rtm->rtm_msglen  = sizeof(struct rt_msghdr)+sizeof(struct sockaddr_in);
    rtm->rtm_version = RTM_VERSION;
    rtm->rtm_type    = RTM_GET;
    rtm->rtm_addrs   = RTA_DST|RTA_IFP;
    rtm->rtm_pid     = pid = MiamiGetPid();
    rtm->rtm_seq     = seq = 1;

    /* set sin */
    sin = (struct sockaddr_in *)(rtm+1);
    memset(sin,0,sizeof(*sin));
    sin->sin_family = AF_INET;
    sin->sin_len    = sizeof(*sin);
    sin->sin_addr   = g->dest.sin_addr;

    /* set it */
    if (0>send(sr,(char *)rtm,rtm->rtm_msglen,0))
    {
        res = ERR_UnreachebleHost;
        goto end;
    }

    /* answer from the stack */
    do
    {
        if (recv(sr,(char *)rtm,1024,0)<0)
        {
            res = ERR_BSDSocket;
            goto end;
        }
    }
    while ((rtm->rtm_type!=RTM_GET) || (rtm->rtm_seq!=seq) || (rtm->rtm_pid!=pid));

    rtm = (struct rt_msghdr *)buf;

    /* inedx -> name */
    if (!if_indextoname(rtm->rtm_index,g->device))
    {
        res = ERR_UnreachebleHost;
        goto end;
    }

    /* a little hack */
    if (((c = g->device[strlen(g->device)-1])<'0')|(c>'9'))
        strcat(g->device,"0");

    /* find if addr */
    strncpy(ifr.ifr_name,g->device,IFNAMSIZ);
    if (IoctlSocket(sd,SIOCGIFADDR,(caddr_t)&ifr)<0)
    {
        res = ERR_BSDSocket;
        goto end;
    }

    memcpy(&g->from.sin_addr,&((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr,4);
    res = 0;

    /* done */

end:
    if (sd>=0) CloseSocket(sd);
    if (sr>=0) CloseSocket(sr);

    return res;
}

/***************************************************************************/
