]>
git.ipfire.org Git - thirdparty/squid.git/blob - lib/rfcnb/session.c
3 /* UNIX RFCNB (RFC1001/RFC1002) NetBIOS implementation
8 * Copyright (C) Richard Sharpe 1996
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29 int RFCNB_saved_errno
= 0;
32 #include "rfcnb/std-includes.h"
33 #include <netinet/tcp.h>
34 #include "rfcnb/rfcnb.h"
35 #include "rfcnb/rfcnb-priv.h"
36 #include "rfcnb/rfcnb-io.h"
37 #include "rfcnb/rfcnb-util.h"
43 int RFCNB_Stats
[RFCNB_MAX_STATS
];
45 RFCNB_Prot_Print_Routine
*Prot_Print_Routine
= NULL
; /* Pointer to protocol print routine */
47 /* Set up a session with a remote name. We are passed Called_Name as a
48 * string which we convert to a NetBIOS name, ie space terminated, up to
49 * 16 characters only if we need to. If Called_Address is not empty, then
50 * we use it to connect to the remote end, but put in Called_Name ... Called
51 * Address can be a DNS based name, or a TCP/IP address ...
55 RFCNB_Call(char *Called_Name
, char *Calling_Name
, char *Called_Address
, int port
)
57 struct RFCNB_Con
*con
;
58 struct in_addr Dest_IP
;
61 struct redirect_addr
*redir_addr
;
62 char *Service_Address
;
64 /* Now, we really should look up the port in /etc/services ... */
67 port
= RFCNB_Default_Port
;
69 /* Create a connection structure first */
71 if ((con
= (struct RFCNB_Con
*) malloc(sizeof(struct RFCNB_Con
))) == NULL
) { /* Error in size */
73 RFCNB_errno
= RFCNBE_NoSpace
;
74 RFCNB_saved_errno
= errno
;
78 con
->fd
= -0; /* no descriptor yet */
79 con
->errn
= 0; /* no error yet */
80 con
->timeout
= 0; /* no timeout */
82 con
->redirect_list
= con
->last_addr
= NULL
;
84 /* Resolve that name into an IP address */
86 Service_Address
= Called_Name
;
87 if (strcmp(Called_Address
, "") != 0) { /* If the Called Address = "" */
88 Service_Address
= Called_Address
;
90 if ((errno
= RFCNB_Name_To_IP(Service_Address
, &Dest_IP
)) < 0) { /* Error */
92 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
97 /* Now connect to the remote end */
99 redirect
= TRUE
; /* Fudge this one so we go once through */
101 while (redirect
) { /* Connect and get session info etc */
103 redirect
= FALSE
; /* Assume all OK */
105 /* Build the redirect info. First one is first addr called */
106 /* And tack it onto the list of addresses we called */
108 if ((redir_addr
= (struct redirect_addr
*) malloc(sizeof(struct redirect_addr
))) == NULL
) { /* Could not get space */
110 RFCNB_errno
= RFCNBE_NoSpace
;
111 RFCNB_saved_errno
= errno
;
116 memcpy((char *) &(redir_addr
->ip_addr
), (char *) &Dest_IP
, sizeof(Dest_IP
));
117 redir_addr
->port
= port
;
118 redir_addr
->next
= NULL
;
120 if (con
->redirect_list
== NULL
) { /* Stick on head */
122 con
->redirect_list
= con
->last_addr
= redir_addr
;
126 con
->last_addr
->next
= redir_addr
;
127 con
->last_addr
= redir_addr
;
131 /* Now, make that connection */
133 if ((Client
= RFCNB_IP_Connect(Dest_IP
, port
)) < 0) { /* Error */
135 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
142 /* Now send and handle the RFCNB session request */
143 /* If we get a redirect, we will comeback with redirect true
144 * and a new IP address in DEST_IP */
146 if ((errno
= RFCNB_Session_Req(con
,
149 &redirect
, &Dest_IP
, &port
)) < 0) {
151 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
153 RFCNB_Close(con
->fd
); /* Close it */
160 /* We have to close the connection, and then try again */
164 RFCNB_Close(con
->fd
); /* Close it */
172 /* We send a packet to the other end ... for the moment, we treat the
173 * data as a series of pointers to blocks of data ... we should check the
176 RFCNB_Send(struct RFCNB_Con
*Con_Handle
, struct RFCNB_Pkt
*udata
, int Length
)
178 struct RFCNB_Pkt
*pkt
;
182 /* Plug in the header and send the data */
184 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
188 RFCNB_errno
= RFCNBE_NoSpace
;
189 RFCNB_saved_errno
= errno
;
193 pkt
->next
= udata
; /* The user data we want to send */
197 /* Following crap is for portability across multiple UNIX machines */
199 *(hdr
+ RFCNB_Pkt_Type_Offset
) = RFCNB_SESSION_MESSAGE
;
200 RFCNB_Put_Pkt_Len(hdr
, Length
);
204 fprintf(stderr
, "Sending packet: ");
208 if ((len
= RFCNB_Put_Pkt(Con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
210 /* No need to change RFCNB_errno as it was done by put_pkt ... */
213 return (RFCNBE_Bad
); /* Should be able to write that lot ... */
216 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
225 /* We pick up a message from the internet ... We have to worry about
226 * non-message packets ... */
228 RFCNB_Recv(void *con_Handle
, struct RFCNB_Pkt
*Data
, int Length
)
230 struct RFCNB_Pkt
*pkt
;
231 // struct RFCNB_Hdr *hdr;
234 if (con_Handle
== NULL
) {
236 RFCNB_errno
= RFCNBE_BadHandle
;
237 RFCNB_saved_errno
= errno
;
241 /* Now get a packet from below. We allocate a header first */
243 /* Plug in the header and send the data */
245 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
249 RFCNB_errno
= RFCNBE_NoSpace
;
250 RFCNB_saved_errno
= errno
;
254 pkt
->next
= Data
; /* Plug in the data portion */
256 if ((ret_len
= RFCNB_Get_Pkt(con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
259 fprintf(stderr
, "Bad packet return in RFCNB_Recv... \n");
265 /* We should check that we go a message and not a keep alive */
274 /* We just disconnect from the other end, as there is nothing in the RFCNB */
275 /* protocol that specifies any exchange as far as I can see */
277 RFCNB_Hangup(struct RFCNB_Con
*con_Handle
)
280 if (con_Handle
!= NULL
) {
281 RFCNB_Close(con_Handle
->fd
); /* Could this fail? */
287 /* Set TCP_NODELAY on the socket */
289 RFCNB_Set_Sock_NoDelay(struct RFCNB_Con
*con_Handle
, BOOL yn
)
292 return (setsockopt(con_Handle
->fd
, IPPROTO_TCP
, TCP_NODELAY
,
293 (char *) &yn
, sizeof(yn
)));
297 /* Listen for a connection on a port???, when */
298 /* the connection comes in, we return with the connection */
306 /* Pick up the last error response as a string, hmmm, this routine should */
307 /* have been different ... */
309 RFCNB_Get_Error(char *buffer
, int buf_len
)
312 if (RFCNB_saved_errno
<= 0) {
313 snprintf(buffer
, (buf_len
- 1), "%s", RFCNB_Error_Strings
[RFCNB_errno
]);
315 snprintf(buffer
, (buf_len
- 1), "%s\n\terrno:%s", RFCNB_Error_Strings
[RFCNB_errno
],
316 strerror(RFCNB_saved_errno
));
320 /* Pick up the last error response and returns as a code */
322 RFCNB_Get_Last_Error()
324 return (RFCNB_errno
);