]>
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 void (*Prot_Print_Routine
)() = NULL
; /* Pointer to print routine */
47 int RFCNB_Get_Last_Errno(void);
48 int RFCNB_Get_Error_Msg(int code
, char *msg_buf
, int len
);
49 void RFCNB_Register_Print_Routine(void (*fn
)());
51 /* Set up a session with a remote name. We are passed Called_Name as a
52 string which we convert to a NetBIOS name, ie space terminated, up to
53 16 characters only if we need to. If Called_Address is not empty, then
54 we use it to connect to the remote end, but put in Called_Name ... Called
55 Address can be a DNS based name, or a TCP/IP address ...
58 void *RFCNB_Call(char *Called_Name
, char *Calling_Name
, char *Called_Address
,
62 struct RFCNB_Con
*con
;
63 struct in_addr Dest_IP
;
66 struct redirect_addr
*redir_addr
;
67 char *Service_Address
;
69 /* Now, we really should look up the port in /etc/services ... */
71 if (port
== 0) port
= RFCNB_Default_Port
;
73 /* Create a connection structure first */
75 if ((con
= (struct RFCNB_Con
*)malloc(sizeof(struct RFCNB_Con
))) == NULL
) { /* Error in size */
77 RFCNB_errno
= RFCNBE_NoSpace
;
78 RFCNB_saved_errno
= errno
;
83 con
-> fd
= -0; /* no descriptor yet */
84 con
-> errn
= 0; /* no error yet */
85 con
-> timeout
= 0; /* no timeout */
88 /* Resolve that name into an IP address */
90 Service_Address
= Called_Name
;
91 if (strcmp(Called_Address
, "") != 0) { /* If the Called Address = "" */
92 Service_Address
= Called_Address
;
95 if ((errno
= RFCNB_Name_To_IP(Service_Address
, &Dest_IP
)) < 0) { /* Error */
97 /* No need to modify RFCNB_errno as it was done by RFCNB_Name_To_IP */
103 /* Now connect to the remote end */
105 redirect
= TRUE
; /* Fudge this one so we go once through */
107 while (redirect
) { /* Connect and get session info etc */
109 redirect
= FALSE
; /* Assume all OK */
111 /* Build the redirect info. First one is first addr called */
112 /* And tack it onto the list of addresses we called */
114 if ((redir_addr
= (struct redirect_addr
*)malloc(sizeof(struct redirect_addr
))) == NULL
) { /* Could not get space */
116 RFCNB_errno
= RFCNBE_NoSpace
;
117 RFCNB_saved_errno
= errno
;
123 memcpy((char *)&(redir_addr
-> ip_addr
), (char *)&Dest_IP
, sizeof(Dest_IP
));
124 redir_addr
-> port
= port
;
125 redir_addr
-> next
= NULL
;
127 if (con
-> redirect_list
== NULL
) { /* Stick on head */
129 con
-> redirect_list
= con
-> last_addr
= redir_addr
;
133 con
-> last_addr
-> next
= redir_addr
;
134 con
-> last_addr
= redir_addr
;
138 /* Now, make that connection */
140 if ((Client
= RFCNB_IP_Connect(Dest_IP
, port
)) < 0) { /* Error */
142 /* No need to modify RFCNB_errno as it was done by RFCNB_IP_Connect */
150 /* Now send and handle the RFCNB session request */
151 /* If we get a redirect, we will comeback with redirect true
152 and a new IP address in DEST_IP */
154 if ((errno
= RFCNB_Session_Req(con
,
157 &redirect
, &Dest_IP
, &port
)) < 0) {
159 /* No need to modify RFCNB_errno as it was done by RFCNB_Session.. */
161 RFCNB_Close(con
->fd
); /* Close it */
169 /* We have to close the connection, and then try again */
171 (con
-> redirects
)++;
173 RFCNB_Close(con
-> fd
); /* Close it */
182 /* We send a packet to the other end ... for the moment, we treat the
183 data as a series of pointers to blocks of data ... we should check the
186 int RFCNB_Send(struct RFCNB_Con
*Con_Handle
, struct RFCNB_Pkt
*udata
, int Length
)
189 struct RFCNB_Pkt
*pkt
;
193 /* Plug in the header and send the data */
195 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
199 RFCNB_errno
= RFCNBE_NoSpace
;
200 RFCNB_saved_errno
= errno
;
205 pkt
-> next
= udata
; /* The user data we want to send */
209 /* Following crap is for portability across multiple UNIX machines */
211 *(hdr
+ RFCNB_Pkt_Type_Offset
) = RFCNB_SESSION_MESSAGE
;
212 RFCNB_Put_Pkt_Len(hdr
, Length
);
216 fprintf(stderr
, "Sending packet: ");
220 if ((len
= RFCNB_Put_Pkt(Con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
222 /* No need to change RFCNB_errno as it was done by put_pkt ... */
224 return(RFCNBE_Bad
); /* Should be able to write that lot ... */
228 /* Now we have sent that lot, let's get rid of the RFCNB Header and return */
238 /* We pick up a message from the internet ... We have to worry about
239 non-message packets ... */
241 int RFCNB_Recv(void *con_Handle
, struct RFCNB_Pkt
*Data
, int Length
)
244 struct RFCNB_Pkt
*pkt
;
245 // struct RFCNB_Hdr *hdr;
248 if (con_Handle
== NULL
) {
250 RFCNB_errno
= RFCNBE_BadHandle
;
251 RFCNB_saved_errno
= errno
;
256 /* Now get a packet from below. We allocate a header first */
258 /* Plug in the header and send the data */
260 pkt
= RFCNB_Alloc_Pkt(RFCNB_Pkt_Hdr_Len
);
264 RFCNB_errno
= RFCNBE_NoSpace
;
265 RFCNB_saved_errno
= errno
;
270 pkt
-> next
= Data
; /* Plug in the data portion */
272 if ((ret_len
= RFCNB_Get_Pkt(con_Handle
, pkt
, Length
+ RFCNB_Pkt_Hdr_Len
)) < 0) {
275 fprintf(stderr
, "Bad packet return in RFCNB_Recv... \n");
282 /* We should check that we go a message and not a keep alive */
292 /* We just disconnect from the other end, as there is nothing in the RFCNB */
293 /* protocol that specifies any exchange as far as I can see */
295 int RFCNB_Hangup(struct RFCNB_Con
*con_Handle
)
299 if (con_Handle
!= NULL
) {
300 RFCNB_Close(con_Handle
-> fd
); /* Could this fail? */
309 /* Set TCP_NODELAY on the socket */
311 int RFCNB_Set_Sock_NoDelay(struct RFCNB_Con
*con_Handle
, BOOL yn
)
315 return(setsockopt(con_Handle
-> fd
, IPPROTO_TCP
, TCP_NODELAY
,
316 (char *)&yn
, sizeof(yn
)));
322 /* Listen for a connection on a port???, when */
323 /* the connection comes in, we return with the connection */
332 /* Pick up the last error response as a string, hmmm, this routine should */
333 /* have been different ... */
335 void RFCNB_Get_Error(char *buffer
, int buf_len
)
339 if (RFCNB_saved_errno
<= 0) {
340 snprintf(buffer
, (buf_len
-1) ,"%s", RFCNB_Error_Strings
[RFCNB_errno
]);
342 snprintf(buffer
, (buf_len
-1), "%s\n\terrno:%s", RFCNB_Error_Strings
[RFCNB_errno
],
343 strerror(RFCNB_saved_errno
));
348 /* Pick up the last error response and returns as a code */
350 int RFCNB_Get_Last_Error()
358 /* Pick up saved errno as well */
360 int RFCNB_Get_Last_Errno()
364 return(RFCNB_saved_errno
);
368 /* Pick up the last error response and return in string ... */
370 int RFCNB_Get_Error_Msg(int code
, char *msg_buf
, int len
)
374 return (strncpy(msg_buf
, RFCNB_Error_Strings
[abs(code
)], len
) != NULL
);
378 /* Register a higher level protocol print routine */
380 void RFCNB_Register_Print_Routine(void (*fn
)())
384 Prot_Print_Routine
= fn
;