1/*
2 * $Id: nbp_unrgstr.c,v 1.6 2009-10-14 02:24:05 didg Exp $
3 *
4 * Copyright (c) 1990,1997 Regents of The University of Michigan.
5 * All Rights Reserved. See COPYRIGHT.
6 */
7
8#ifdef HAVE_CONFIG_H
9#include "config.h"
10#endif /* HAVE_CONFIG_H */
11
12#include <string.h>
13#include <errno.h>
14#include <signal.h>
15
16#include <sys/types.h>
17#include <sys/param.h>
18#include <sys/socket.h>
19#include <sys/time.h>
20
21#include <netatalk/endian.h>
22#include <netatalk/at.h>
23#include <atalk/nbp.h>
24#include <atalk/netddp.h>
25#include <atalk/ddp.h>
26
27#ifdef HAVE_NETDB_H
28#include <netdb.h>
29#endif /* HAVE_NETDB_H */
30#include  "nbp_conf.h"
31
32/* FIXME/SOCKLEN_T: socklen_t is a unix98 feature. */
33#ifndef SOCKLEN_T
34#define SOCKLEN_T unsigned int
35#endif /* ! SOCKLEN_T */
36
37int nbp_unrgstr(const char *obj,const char *type,const char  *zone, const struct at_addr *addr)
38{
39    struct sockaddr_at	to;
40    struct nbphdr	nh;
41    struct timeval	timeout;
42    fd_set		readfd;
43    struct servent	*se;
44    char		*data;
45    int			s, cc;
46    SOCKLEN_T		namelen;
47
48
49    memset(&to, 0, sizeof(to));
50    if ((s = netddp_open(&to, NULL)) < 0)
51	return -1;
52
53    data = nbp_send;
54    *data++ = DDPTYPE_NBP;
55    nh.nh_op = NBPOP_UNRGSTR;
56    nh.nh_cnt = 1;
57    nh.nh_id = ++nbp_id;
58    memcpy( data, &nh, SZ_NBPHDR );
59    data += SZ_NBPHDR;
60
61    memset(data, 0, SZ_NBPTUPLE);
62    data += SZ_NBPTUPLE;
63
64    if ( obj ) {
65	if (( cc = strlen( obj )) > NBPSTRLEN ) return( -1 );
66	*data++ = cc;
67	memcpy( data, obj, cc );
68	data += cc;
69    } else {
70	*data++ = 0;
71    }
72
73    if ( type ) {
74	if (( cc = strlen( type )) > NBPSTRLEN ) return( -1 );
75	*data++ = cc;
76	memcpy( data, type, cc );
77	data += cc;
78    } else {
79	*data++ = 0;
80    }
81
82    if ( zone ) {
83	if (( cc = strlen( zone )) > NBPSTRLEN ) return( -1 );
84	*data++ = cc;
85	memcpy( data, zone, cc );
86	data += cc;
87    } else {
88	*data++ = 0;
89    }
90
91    memset( &to, 0, sizeof( struct sockaddr_at ));
92    to.sat_family = AF_APPLETALK;
93    if (addr)
94      memcpy(&to.sat_addr, addr, sizeof(struct at_addr));
95#ifdef BSD4_4
96    to.sat_len = sizeof( struct sockaddr_at );
97#endif /* BSD4_4 */
98
99    if ( nbp_port == 0 ) {
100	if (( se = getservbyname( "nbp", "ddp" )) == NULL ) {
101	    nbp_port = 2;
102	} else {
103	    nbp_port = ntohs( se->s_port );
104	}
105    }
106    to.sat_port = nbp_port;
107
108    if ( netddp_sendto( s, nbp_send, data - nbp_send, 0,
109			(struct sockaddr *)&to,
110			sizeof( struct sockaddr_at )) < 0 ) {
111        goto unregister_err;
112    }
113
114    FD_ZERO( &readfd );
115    FD_SET( s, &readfd );
116    timeout.tv_sec = 2;
117    timeout.tv_usec = 0;
118    if (( cc = select( s + 1, &readfd, NULL, NULL, &timeout )) < 0 ) {
119        goto unregister_err;
120    }
121    if ( cc == 0 ) {
122	errno = ETIMEDOUT;
123        goto unregister_err;
124    }
125
126    namelen = sizeof( struct sockaddr_at );
127    if (( cc = netddp_recvfrom( s, nbp_recv, sizeof( nbp_recv ), 0,
128			(struct sockaddr *)&to, &namelen )) < 0 ) {
129        goto unregister_err;
130    }
131    netddp_close( s );
132
133    data = nbp_recv;
134    if ( *data++ != DDPTYPE_NBP ) {
135	return( -1 );
136    }
137    memcpy( &nh, data, SZ_NBPHDR );
138    if ( nh.nh_op != NBPOP_OK ) {
139	return( -1 );
140    }
141    return( 0 );
142
143unregister_err:
144    netddp_close(s);
145    return -1;
146}
147