Sunteți pe pagina 1din 580

Dynamic C TCP/IP

Users Manual
030424 019-0100-G

This manual (or an even more up-to-date revision) is available for free download at the Z-World website: www.zworld.com.

Dynamic C TCP/IP Users Manual


Part Number 030424 019-0100G Printed in U.S.A. 2002 Z-World Inc. All rights reserved. Z-World reserves the right to make changes and improvements to its products without providing notice.

Trademarks
Dynamic C is a registered trademark of Z-World Inc. Windows is a registered trademark of Microsoft Corporation

Z-World, Inc.
2900 Spafford Street Davis, California 95616-6800 USA Telephone: 530.757.3737 Fax: 530.757.3792 or 530.753.5141 www.zworld.com

ii

Dynamic C TCP/IP Users Manual

Table of Contents
1 2 Introduction .................................................1 TCP/IP Initialization .................................3
2.1 TCP/IP Stack Configuration.....................3 Multiple Interface Support....................3 Interface Selection Macros ...................5 Single Interface Support .......................7 TCP/IP Stack Initialization ...................7 2.2 Interface Configuration ............................8 Configuration Overview .......................8 Sources of Configuration Information..9 2.3 Dynamically Starting and Stopping Interfaces ............................................15 Testing Interface Status.......................15 Bringing an Interface Up ....................15 Bringing an Interface Down ...............16 2.4 Setting up PPP Interfaces .......................17 PPP over Asynchronous Serial ...........17 PPP over Ethernet ...............................17 2.5 Configuration Macro Reference .............18 Removing Unnecessary Functions .....18 Including Additional Functions ..........18 BOOTP/DHCP Control Macros .........19 BOOTP/DHCP Global Variables........20 Buffer and Resource Sizing ................22 Pre Version 7.30 Network Configuration 25 Version 7.30 Interface Configuration .26 Time-Outs and Retry Counters ...........28 Program Debugging............................29 Miscellaneous Macros ........................30 Status Function for UDP Sockets .......42 I/O Functions for UDP Sockets ..........42 3.7 UDP Socket Functions (pre 7.05)...........43 I/O Functions for UDP Sockets ..........43 Opening and Closing a UDP Socket...43 Writing to a UDP Socket ....................43 Reading From a UDP Socket..............44 Porting Programs from the older UDP API to the new UDP API ............44 3.8 Skeleton Program ...................................45 TCP/IP Stack Initialization .................46 Packet Processing ...............................46 3.9 TCP/IP Daemon: tcp_tick()....................46 tcp_tick() for Robust Applications .....47 Global Timer Variables.......................47 3.10 State-Based Program Design ................47 Blocking vs. Non-Blocking ................48 3.11 TCP and UDP Data Handlers ...............49 UDP Data Handler..............................51 TCP Data Handler ..............................51 3.12 Multitasking and TCP/IP......................53 C/OS-II .............................................53 Cooperative Multitasking ...................53

Optimizing TCP/IP Performance ........57


4.1 DBP and Sizing of TCP Buffers.............58 4.2 TCP Performance Tuning.......................60 The Nagle Algorithm..........................60 Time-Out Settings...............................61 Reserved Ports ....................................64 Type of Service (TOS)........................65 ARP Cache Considerations ................65 4.3 Writing a Fast UDP Request/Response Server..................................................66 4.4 Tips and Tricks for TCP Applications....66 Bulk Loader Applications...................67 Casual Server Applications ................68 Master Controller Applications ..........68 Web Server Applications ....................68 Protocol Translator Applications ........68

TCP and UDP Socket Interface ...........33 3.1 What is a Socket? ...................................34 Port Numbers ......................................34 3.2 Allocating TCP and UDP Sockets..........35 Allocating Socket Buffers...................35 Socket Buffer Sizes.............................36 3.3 Opening TCP Sockets.............................36 Passive Open.......................................36 Active Open ........................................37 Waiting for Connection Establishment ... 37 Specifying a Listen Queue..................38 3.4 TCP Socket Functions ............................38 Control Functions for TCP Sockets....38 Status Functions for TCP Sockets ......39 I/O Functions for TCP Sockets...........40 3.5 UDP Socket Overview ...........................41 3.6 UDP Socket Functions (7.05 and later) ..42 Control Functions for UDP Sockets ..42

Network Addressing: ARP & DNS....69


5.1 5.2 5.3 5.4 ARP Functions .......................................69 Configuration Macros for ARP ..............69 DNS Functions .......................................71 Configuration Macros for DNS Lookups ... 71

IGMP and Multicasting .........................73


6.1 Multicasting............................................73 Multicast Addresses............................73
iii

TCP/IP Users Manual

Host Group Membership.................... 73 6.2 IGMP ..................................................... 73 6.3 Multicast Macros ................................... 74

Function Reference ................................. 75


_abort_socks ...................................... 76 arpcache_create ................................. 77 arpcache_flush .................................. 78 arpcache_hwa .................................... 79 arpcache_iface ................................... 80 arpcache_ipaddr ................................ 81 arpcache_load .................................... 82 arpcache_search ................................ 84 _arp_resolve ...................................... 85 arpresolve_check ............................... 86 arpresolve_ipaddr .............................. 87 arpresolve_start ................................. 88 aton ............................................. 89 _chk_ping .......................................... 90 dhcp_acquire ..................................... 91 dhcp_get_timezone ........................... 92 dhcp_release ...................................... 93 getdomainname ................................. 94 gethostid ............................................ 95 gethostname ...................................... 96 getpeername ...................................... 97 getsockname ...................................... 98 htonl ............................................. 99 htons ........................................... 100 ifconfig ........................................... 101 ifdown ........................................... 108 ifpending ......................................... 109 ifstatus ........................................... 110 ifup ........................................... 111 inet_addr .......................................... 112 inet_ntoa .......................................... 113 ip_iface ........................................... 114 ip_print_ifs ...................................... 115 ip_timer_expired ............................. 116 ip_timer_init .................................... 117 is_valid_iface .................................. 118 multicast_joingroup ........................ 119 multicast_leavegroup ...................... 120 ntohl ........................................... 121 ntohs ........................................... 122 paddr ........................................... 123 pd_getaddress .................................. 124

pd_havelink ..................................... 125 pd_powerdown ................................ 126 pd_powerup ..................................... 127 _ping ........................................... 128 psocket ........................................... 129 resolve ........................................... 130 resolve_cancel ................................. 131 resolve_name_check ....................... 132 resolve_name_start .......................... 133 rip ........................................... 134 router_add ....................................... 135 router_del_all .................................. 135 router_delete .................................... 136 router_for ........................................ 137 router_print ...................................... 138 router_printall .................................. 139 _send_ping ...................................... 140 setdomainname ................................ 141 sethostid .......................................... 142 sethostname ..................................... 143 sock_abort ....................................... 144 sock_alive ........................................ 145 sock_aread ....................................... 146 sock_awrite ..................................... 147 sock_axread ..................................... 148 sock_axwrite ................................... 149 sock_bytesready .............................. 150 sock_close ....................................... 151 sock_dataready ................................ 152 sockerr ........................................... 153 sock_error ........................................ 154 sock_established .............................. 155 sock_fastread ................................... 156 sock_fastwrite ................................. 157 sock_flush ....................................... 158 sock_flushnext ................................ 159 sock_getc ......................................... 160 sock_gets ......................................... 161 sock_iface ........................................ 162 sock_init .......................................... 163 sock_mode ...................................... 164 sock_noflush ................................... 166 sock_perror ...................................... 167 sock_preread ................................... 168 sock_putc ........................................ 169 sock_puts ......................................... 170 sock_rbleft ....................................... 171
TCP/IP Users Manual

iv

sock_rbsize ......................................172 sock_rbused .....................................173 sock_read .........................................174 sock_recv .........................................175 sock_recv_from ...............................177 sock_recv_init ..................................178 sock_resolved ..................................179 sock_set_tos .....................................180 sock_set_ttl ......................................181 sockstate ...........................................182 sock_tbleft .......................................183 sock_tbsize .......................................184 sock_tbused .....................................185 sock_tick ..........................................186 sock_wait_closed .............................187 sock_wait_established .....................188 sock_wait_input ...............................189 sock_write ........................................190 sock_xfastread .................................191 sock_xfastwrite ................................192 sock_yield ........................................193 tcp_clearreserve ...............................194 tcp_config ........................................195 tcp_extlisten .....................................196 tcp_extopen ......................................197 tcp_keepalive ...................................198 tcp_listen ..........................................199 tcp_open ...........................................201 tcp_reserveport ................................203 tcp_tick ............................................204 udp_bypass_arp ...............................205 udp_close .........................................206 udp_extopen .....................................207 udp_open .........................................209 udp_peek ..........................................211 udp_recv ..........................................212 udp_recvfrom ...................................213 udp_send ..........................................214 udp_sendto .......................................215 udp_waitopen ...................................216 udp_waitsend ...................................217 udp_xsendto .....................................218

Server Utility Library ...........................219


8.1 Data Structures for Zserver.lib .............219 ServerSpec Structure ........................219 ServerAuth Structure ........................219 FormVar Structure ............................219

8.2 Constants Used in Zserver.lib...............220 ServerSpec Type Field......................220 ServerSpec Vartype Field .................220 Servermask field ...............................220 Configuration Macros.......................221 8.3 HTML Forms .......................................221 8.4 API Functions.......................................221 sauth_adduser .................................. 222 sauth_authenticate ........................... 223 sauth_getpassword........................... 224 sauth_getuserid ................................ 225 sauth_getusername........................... 226 sauth_getwriteaccess ....................... 227 sauth_removeuser ............................ 228 sauth_setpassword ........................... 229 ........................................... 230 sauth_setwriteaccess ........................ 231 sspec_addform ................................. 232 sspec_addfsfile................................. 233 sspec_addfunction ........................... 234 sspec_addfv ..................................... 235 sspec_addrootfile ............................. 236 sspec_adduser .................................. 237 sspec_addvariable............................ 238 sspec_addxmemfile ......................... 239 sspec_addxmemvar.......................... 240 sspec_aliasspec ................................ 241 sspec_checkaccess ........................... 242 sspec_findfv..................................... 243 sspec_findname ............................... 244 sspec_findfsname............................. 245 sspec_findnextfile............................ 246 sspec_getfileloc ............................... 247 sspec_getfiletype ............................. 248 sspec_getformtitle............................ 249 sspec_getfunction ............................ 250 sspec_getfvdesc ............................... 251 sspec_getfventrytype ....................... 252 sspec_getfvlen ................................. 253 sspec_getfvname.............................. 254 sspec_getfvnum ............................... 255 sspec_getfvopt ................................. 256 sspec_getfvoptlistlen ....................... 257 sspec_getfvreadonly ........................ 258 sspec_getfvspec ............................... 259 sspec_getlength................................ 260 sspec_getname ................................. 261 sspec_getpreformfunction ............... 262 sspec_getrealm................................. 263 sspec_gettype................................... 264

TCP/IP Users Manual

sspec_getuserid ............................... sspec_getusername.......................... sspec_getvaraddr ............................. sspec_getvarkind ............................. sspec_getvartype ............................. sspec_needsauthentication .............. sspec_readfile.................................. sspec_readvariable .......................... sspec_remove .................................. sspec_removeuser ........................... sspec_resizerootfile ......................... sspec_restore ................................... sspec_save....................................... sspec_setformepilog........................ sspec_setformfunction .................... sspec_setformprolog ....................... sspec_setformtitle............................ sspec_setfvcheck ............................. sspec_setfvdesc ............................... sspec_setfventrytype ....................... sspec_setfvfloatrange ...................... sspec_setfvlen ................................. sspec_setfvname.............................. sspec_setfvoptlist ............................ sspec_setfvrange ............................. sspec_setfvreadonly ........................ sspec_setpreformfunction ............... sspec_setrealm ................................ sspec_setsavedata............................ sspec_setuser ...................................

265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294

http_date_str.................................... http_delfile ...................................... http_finderrbuf ................................ http_findname ................................. http_handler .................................... http_idle .......................................... http_init .......................................... http_nextfverr.................................. http_parseform ................................ http_scanpost................................... http_setauthentication ..................... http_setcookie ................................. http_urldecode................................. shtml_addfunction........................... shtml_addvariable ........................... shtml_delfunction............................ shtml_delvariable ............................

330 330 331 331 332 332 333 333 334 335 336 337 338 339 340 341 341

10 FTP Client ............................................... 343


10.1 Configuration Macros ........................ 343 10.2 API Functions .................................... 344 ftp_client_setup............................... 344 ftp_client_tick ................................. 345 ftp_client_filesize............................ 346 ftp_client_xfer................................. 347 ftp_data_handler.............................. 348 ftp_last_code ................................... 350 10.3 Sample FTP Transfer ......................... 351

11 FTP Server .............................................. 353


11.1 Configuration Macros ........................ 354 11.2 File Handlers ...................................... 356 Replacing the Default Handlers ....... 356 File Handlers Specification.............. 356 ftp_dflt_open................................... 357 ftp_dflt_getfilesize .......................... 358 ftp_dflt_read.................................... 359 ftp_dflt_write .................................. 360 ftp_dflt_close .................................. 361 ftp_dflt_list...................................... 362 ftp_dflt_cd....................................... 363 ftp_dflt_pwd.................................... 364 ftp_dflt_mdtm ................................. 365 ftp_dflt_delete ................................. 366 11.3 API Functions .................................... 367 ftp_dflt_is_auth ............................... 367 ftp_init .......................................... 368 ftp_load_filenames.......................... 369 ftp_save_filenames.......................... 370 ftp_set_anonymous ......................... 371 ftp_shutdown................................... 372
TCP/IP Users Manual

HTTP Server ........................................... 295 9.1 HTTP Server Data Structures .............. 296 HttpSpec........................................... 296 HttpType........................................... 297 HttpRealm ........................................ 297 HttpState........................................... 298 9.2 Configuration Macros .......................... 301 Customizing HTTP headers ............. 303 9.3 File Compression Support ................... 304 9.4 Sample Programs ................................. 305 Serving Static Web Pages................. 306 Dynamic Web Pages Without HTML Forms ........................................ 308 Web Pages With HTML Forms........ 312 HTML Forms Using Zserver.lib ...... 320 9.5 API Functions ...................................... 326 cgi_redirectto .................................. 326 cgi_sendstring ................................. 327 http_addfile ..................................... 328 http_contentencode ......................... 329

vi

11.4 11.5 11.6 11.7

ftp_tick ........................................... 373 Sample FTP Server .............................374 Getting Through a Firewall ................375 FTP Server Commands.......................375 Reply Codes to FTP Commands ........377

12 TFTP Client .............................................379


12.1 BOOTP/DHCP ...................................379 12.2 Data Structure for TFTP .....................380 12.3 API Functions.....................................380 tftp_init ........................................... 381 tftp_initx .......................................... 382 tftp_tick ........................................... 383 tftp_tickx.......................................... 384 tftp_exec .......................................... 385

13 SMTP Mail Client .................................387


13.1 Sample Conversation..........................387 13.2 Configuration Macros.........................388 13.3 API Functions.....................................389 smtp_sendmail ................................. 389 smtp_sendmailxmem ....................... 390 smtp_mailtick .................................. 391 smtp_status ...................................... 392 13.4 Sample Sending of an E-mail .............393

14 POP3 Client .............................................395


14.1 Configuration......................................395 14.2 Steps to Receive E-mail......................396 14.3 Call-Back Function.............................396 Normal call-back ..............................396 POP_PARSE_EXTRA call-back ......396 14.4 API Functions.....................................397 pop3_init .......................................... 397 pop3_getmail ................................... 398 pop3_tick ......................................... 399 14.5 Sample Receiving of E-mail...............400 Sample Conversation ........................401

15 SNMP ........................................................403
15.1 SNMP Overview ................................403 Managed Objects ..............................404 SNMP Agent.....................................404 MIBs ............................................405 SMI ............................................406 15.2 Demo Program....................................408 Creating Managed Objects ...............409 Callback Functions ...........................410 Creating Communities ......................412 Creating the MIB ..............................413 Defining Managed Objects with SMI..... 415

Running the SNMP Agent ................419 15.3 Configuration Macros........................420 15.4 API Functions.....................................422 snmp_add......................................... 422 snmp_add_community..................... 425 snmp_append_binary_oid................ 426 snmp_append_binary_stem ............. 427 snmp_append_oid ............................ 428 snmp_append_parse_oid ................. 429 snmp_append_parse_stem ............... 430 snmp_append_stem ......................... 431 snmp_community_mask .................. 432 snmp_community_name.................. 433 snmp_copy_oid................................ 434 snmp_delete ..................................... 435 snmp_format_oid............................. 436 snmp_get.......................................... 437 snmp_get_indexed ........................... 438 snmp_get_next................................. 439 snmp_init_parms ............................. 440 snmp_last_index .............................. 441 snmp_last_int................................... 442 snmp_last_len .................................. 443 snmp_last_long ................................ 444 snmp_last_maxlen ........................... 445 snmp_last_mem ............................... 446 snmp_last_objectID ......................... 447 snmp_last_snmp_type ..................... 448 snmp_last_type ................................ 449 snmp_last_xmem ............................. 450 snmp_monitor .................................. 451 snmp_print_tree ............................... 454 snmp_set_access.............................. 455 snmp_set_callback........................... 456 snmp_set_community ...................... 457 snmp_set_dflt_communities ............ 458 snmp_set_foct.................................. 459 snmp_set_int.................................... 460 snmp_set_long ................................. 461 snmp_set_objectID .......................... 462 snmp_set_oct ................................... 463 snmp_set_oid ................................... 464 snmp_set_parse_oid......................... 465 snmp_set_parse_stem ...................... 466 snmp_set_stem................................. 467 snmp_set_str .................................... 468 snmp_start........................................ 469 snmp_stop ........................................ 470 snmp_time_since ............................. 471 snmp_timeticks ................................ 472
vii

TCP/IP Users Manual

snmp_trap........................................ snmp_unmonitor ............................. snmp_up_oid ................................... snmp_up_stem ................................ snmp_used....................................... snmp_xadd ......................................

473 474 475 476 477 478

16 Telnet......................................................... 479
16.1 Telnet (Dynamic C 7.05 and later)..... 479 Setup ........................................... 479 API Functions (Dynamic C 7.05 and later) .......................................... 480 vserial_close............................. 480 vserial_init ............................... 481 vserial_keepalive ..................... 482 vserial_listen ............................ 483 vserial_open ............................. 484 vserial_tick............................... 485 16.2 Telnet (pre-Dynamic C 7.05) ............. 486 Configuration Macros ...................... 486 API Functions .................................. 486 telnet_init ................................. 486 telnet_tick................................. 487 telnet_close .............................. 487 An Example Telnet Server ............... 488 An Example Telnet Client................ 489

con_reset_io ............................. 510 con_set_backup_lx................... 511 con_set_files_lx ....................... 511 con_set_user_idle..................... 512 con_set_timeout ....................... 512 con_set_user_timeout .............. 513 console_disable........................ 513 console_enable......................... 514 Zconsole Execution Choices............ 515 17.7 Backup System .................................. 516 Data Structure for Backup System... 516 Array Definition for Backup System 517 17.8 Zconsole Macros................................ 518 17.9 Sample Program................................. 521

18 PPP Driver ............................................... 527


18.1 PPP Libraries ..................................... 527 18.2 Operation Details for PPP over Serial 528 The Modem Interface....................... 528 Flow Control .................................... 529 18.3 Operation Details for PPPoE ............. 530 18.4 Link Control Protocol Options .......... 530 18.5 Configuring PPP (pre 7.30) ............... 531 Using a Modem with PPP ................ 531 Selecting a Serial Port ...................... 532 IP Addresses..................................... 532 Authentication.................................. 532 Link Teardown ................................. 534 18.6 Configuring PPP (Dynamic C 7.30) .. 535 Serial Port Selection......................... 535 PPPoE Port Selection ....................... 535 ifconfig() Options for PPP ............... 536 ifconfig() Options for Serial PPP .... 537 Starting and Stopping PPP Interfaces .... 539 18.7 API Functions .................................... 540 Using Cofunctions............................ 540 CofModemExpect ........................... 540 CofModemHangup......................... 541 CofModemInit................................. 541 CofModemSend .............................. 542 CofPPPshutdown ............................ 542 CofPPPstart ..................................... 543 ModemClose ................................... 543 ModemConnected ........................... 544 ModemExpect ................................. 544 ModemHangup............................... 545 ModemInit....................................... 545 ModemOpen.................................... 546 ModemReady .................................. 546 ModemRinging ............................... 547 ModemSend .................................... 547
TCP/IP Users Manual

17 General Purpose Console .................... 491


17.1 Zconsole Features .............................. 491 File System Requirement ................. 491 TCP/IP and Zconsole ....................... 491 17.2 Login Name and Password ................ 492 17.3 Zconsole Commands and Messages .. 492 Zconsole Command Data Structure . 492 17.4 Zconsole Command Array................. 494 Zconsole Commands........................ 494 Zconsole Error Messages ................. 501 17.5 Zconsole I/O Interface ....................... 504 How to Include an I/O Method ........ 504 Predefined I/O Methods ................... 504 Multiple I/O Streams....................... 505 17.6 Zconsole Execution............................ 506 File System Initialization ................. 506 Serial Buffers ................................... 506 Using TCP/IP ................................... 506 Required Zconsole Functions........... 507 console_init .............................. 507 console_tick ............................. 507 Useful Zconsole Function ................ 508 con_backup .............................. 508 con_backup_bytes.................... 508 con_backup_reserve................. 509 con_chk_timeout...................... 509 con_load_backup ..................... 510
viii

ModemStartPPP............................... 548 PPPactive ......................................... 548 PPPclose .......................................... 548 PPPinit ........................................... 549 PPPflowcontrolOff .......................... 549 PPPflowcontrolOn ........................... 550 PPPstart ........................................... 550 PPPnegotiateIP ................................ 551 PPPnegotiateDNS ............................ 551 PPPSerialGetErrors ......................... 552 PPPsetAuthenticatee ........................ 553 PPPsetAuthenticator ........................ 553 PPPshutdown ................................... 554 ResetPPP.......................................... 554

Notice to Users ......................................555 Index ..........................................................557

TCP/IP Users Manual

ix

TCP/IP Users Manual

1. Introduction
This manual is intended for embedded system designers and support professionals who are using a Rabbit-based controller board. Most of the information contained here is meant for use with Ethernet-enabled boards, but using only serial communication is also an option. Knowledge of networks and TCP/IP (Transmission Control Protocol/Internet Protocol ) is assumed. For an overview of these two topics a separate manual is provided, An Introduction to TCP/IP. A basic understanding of HTML (HyperText Markup Language) is also assumed. For information on this subject, there are numerous sources on the Web and in any major book store. The Dynamic C implementation of TCP/IP comprises several libraries. The main library is DCRTCP.LIB. As of Dynamic C 7.05, this library is a light wrapper around DNS.LIB, IP.LIB, NET.LIB, TCP.LIB and UDP.LIB. These libraries implement DNS (Domain Name Server), IP, TCP, and UDP (User Datagram Protocol). This, along with the libraries ARP.LIB, ICMP.LIB, IGMP.LIB and PPP.LIB are the transport and network layers of the TCP/IP protocol stack. The Dynamic C libraries: BOOTP.LIB FTP_SERVER.LIB FTP_CLIENT.LIB HTTP.LIB POP3.LIB SMNP.LIB SMTP.LIB TFTP.LIB VSERIAL.LIB implement application-layer protocols. All user-callable functions are listed and described in their appropriate chapter. Example programs throughout the manual illustrate the use of all the different protocols. The sample code also provides templates for creating servers and clients of various types. To address embedded system design needs, additional functionality has been included in Dynamic Cs implementation of TCP/IP. There are step-by-step instructions on how to create HTML forms, allowing remote access and manipulation of information. There is also a serial-based console that can be used with TCP/IP to open up legacy systems for additional control and monitoring. The console may also be used for configuration when a serial port is available. Multiple interfaces are supported starting with Dynamic C version 7.30.

Introduction

TCP/IP Users Manual

2. TCP/IP Initialization
This chapter describes the configuration macros, data structures and functions used to configure and initialize the Dynamic C TCP/IP stack. Starting with Dynamic C version 7.30, the stack supports multiple interfaces. Interface configuration is described in Section 2.2. The Dynamic C TCP/IP stack supports IP version 4. Although multiple interfaces are supported starting with 7.30, the TCP/IP stack does not support packet routing at the IP level.

2.1 TCP/IP Stack Configuration


You will need to know certain things to configure the stack. You will need to know which interfaces will be used and how many. You will also need to determine the necessary software functionality. For example, will there be DNS lookups? Are TCP and UDP protocols both necessary? Will DHCP be used? The ability to remove unneeded features via conditional compilation has been enhanced starting with Dynamic C 7.30. This is accomplished with the configuration macros described in Section 2.5.1 and Section 2.5.2.

2.1.1 Multiple Interface Support


The supported interfaces are:

Ethernet PPP (Point-to-Point Protocol) over a serial link PPP over Ethernet
The interfaces must be on distinct, non-overlapping subnets. In particular, each interface must be assigned a unique IP address, known as the home IP address for that interface. The interfaces available to your application will depend on the hardware configuration of the target board. All Rabbit-based boards have at least 4 asynchronous serial ports, so PPP over serial is always available. Many boards have an Ethernet port. If an Ethernet port is available, then it may be used for normal Ethernet or PPP over Ethernet (PPPoE). No Z-World board has more than one Ethernet port, however Dynamic C 7.30 contains support for a second Ethernet if and when such a board becomes available.

Chapter 2: TCP/IP Initialization

Your application uses configuration macros to select the interface(s) to use for TCP/IP. Each hardware interface will have an interface number assigned. The interface number is not used directly; instead, your application should use the macros defined for this purpose. If you are writing general-purpose routines, then you should include #ifdef tests for the interface macro if you need to refer to it. This is because the macros are not necessarily defined for non-existent interfaces. The macros are:

IF_ETH0, IF_ETH1
These macros represent Ethernet ports that are not using PPP. IF_ETH0 refers to the first (and currently only) Ethernet port.

IF_PPPOE0, IF_PPPOE1
These macros represent Ethernet ports used for PPP over Ethernet. IF_PPPOE0 refers to the first (and currently only) Ethernet port. PPPoE and regular Ethernet can co-exist on the same Ethernet hardware. PPPoE effectively sets up a virtual point-to-point link between two devices on the same Ethernet LAN segment.

IF_PPP0, IF_PPP1, IF_PPP2, IF_PPP3, IF_PPP4, IF_PPP5


These macros represent asynchronous serial ports used for PPP. IF_PPP0 always refers to serial port A, IF_PPP1 refers to serial port B, etc. Most boards will avoid using serial port A, since it is most often used for Dynamic C debugging and program download.

IF_PPPX
This is an alias for the first PPP interface. The first PPP interface is selected as the first valid interface in the following order: IF_PPPOE0, IF_PPPOE1, IF_PPP0, IF_PPP1, etc. through to IF_PPP5.

IF_DEFAULT
This is an alias for the default interface. You can explicitly define this macro prior to including dcrtcp.lib to select a default interface. The Dynamic C TCP/IP libraries do not make use of IF_DEFAULT with the important exception of DHCP. DHCP only works on the default interface. If you do not explicitly define IF_DEFAULT, it is chosen as the first valid interface in the following order: IF_PPPX (see above), IF_ETH0, IF_ETH1. If you explicitly define IF_DEFAULT, then you must define it to a hard-coded integer value, not one of the IF_* macros, since the IF_* macros are not defined until dcrtcp.lib is included. Since the actual numbers assigned to each interface depend on the values of the USE_* macros, you must be careful when doing this. The only time you may want to explicitly define IF_DEFAULT is when you are using both PPP and non-PPPoE Ethernet, and you want to use DHCP on the Ethernet interface.

TCP/IP Users Manual

IF_ANY
This is not an interface as such. It is a special value used to denote any or all interfaces, where applicable. This macro should be used only where a function documents that its use is acceptable. For example, the tcp_extlisten() function accepts IF_ANY as an interface parameter, which tells it to listen for incoming connections on any available interface.

2.1.2 Interface Selection Macros


As each physical interface has its own macro, each type of interface has a corresponding macro. The macro value determines which physical interfaces of the same type will be supported by the stack. Setting the macro to zero disables support for that type of interface, i.e., no physical interfaces of that type will be supported. If the macros are not defined in the application program, they will be set to zero internally.

USE_ETHERNET
This macro allows support of non-PPPoE Ethernet. It can be set to 0x01, 0x02 or 0x03. Most boards only support 0x01, meaning the first non-PPPoE Ethernet device. Boards with two Ethernet devices can set this macro to 0x02, referring to the second Ethernet device, or 0x03 to allow use of both devices.

USE_PPP_SERIAL
This macro allows support of PPP over asynchronous serial. It can be set to

0x01 (serial port A) 0x02 (serial port B) 0x04 (serial port C) 0x08 (serial port D) or any bitwise combination of these 4 values

Serial port C is the default, but you may use any of the others. Please note that if you use serial port A (the programming port) Dynamic C will not be able to communicate with the target. You may also need to define other macros to allow correct functioning of the serial port hardware, e.g., hardware flow control.

USE_PPPOE
This macro allows support of PPP over Ethernet. It is set in the same way as USE_ETHERNET. The bitmask indicates which Ethernet devices are to be used for PPP over Ethernet.

Chapter 2: TCP/IP Initialization

2.1.2.1 Link Layer Drivers The USE_* configuration macros described in Section 2.1.2 cause the appropriate link layer drivers to be included. If none of the USE_* macros are defined and the macro PKTDRV is also not defined, realtek.lib will be used. Some board types cause a driver other than realtek.lib to be used, e.g., if the board is a RCM 3200 or 3210, the packet driver library asix.lib will replace realtek.lib. The following table tells which link layer drivers will be used when a USE_* macro is defined to a value greater than zero.
Table 1. Libraries included when USE_* macro value > zero Configuration Macro Realtek.lib* Ppp.lib Ppplink.lib Pppoe.lib

USE_ETHERNET USE_PPP_SERIAL USE_PPPOE

yes no yes

no yes yes

no yes no

no no yes

* or a substitute packet driver library based on board type

As the table reveals, using PPP over Ethernet causes realtek.lib, ppp.lib and pppoe.lib to be included. Multiple drivers may also be included by defining multiple interfaces. For example, defining USE_PPP_SERIAL and USE_PPPOE to values greater than zero will also cause all libraries to be included. If your application needs to perform conditional compilation that depends on the drivers actually included, then the following macros are defined:

USING_ETHERNET USING_PPP_SERIAL USING_PPPOE


These macros are always defined, but will have a zero value if the driver was not included. Thus, the conditional compilation should use the #if operator, not #ifdef. For example, #if USING_PPP_SERIAL // Do something special for PPP over serial #endif The value assigned to the USING_* macro is the number of hardware interfaces of that type that are available. On a Rabbit 2000 board, USING_PPP_SERIAL will be defined to 4 or 0. On a Rabbit 3000 board, the value will be 6 or 0. An additional macro, USING_PPP, is also defined if any of the PPP-type interfaces are in use. Unlike the above macros, this macro is either defined or not defined, so the correct test is #ifdef.

TCP/IP Users Manual

2.1.3 Single Interface Support


Backwards compatibility exists for applications compiled with earlier versions of Dynamic C. If none of the USE_* macros are defined, then the old behavior (pre-Dynamic C 7.30) is used, which is to include one, and only one, link layer driver. 2.1.3.1 Configuration Macros for Link Layer Driver - Single Interface Do not define either of these macros if any of the USE_* macros are defined.

PKTDRV
This macro specifies the packet driver to use. Include one of the following statements in your application. #define PKTDRV realtek.lib #define PKTDRV ppp.lib // To use Ethernet // To use PPP (serial or Ethernet)

PPPOE
This macro is defined to use PPP over Ethernet when PKTDRV is set to ppp.lib. For other packet drivers, this define has no effect (but should not be defined in order to avoid problems with future Dynamic C releases). #define PPPOE

2.1.4 TCP/IP Stack Initialization


The function sock_init() must be called near the start of your main() function in order to initialize the TCP/IP stack. The return value from sock_init() must indicate success before calling any other TCP/IP functions, with the possible exception of ifconfig().
IMPORTANT: If you are using C/OS-II, then you must ensure that OSInit() is

called before calling sock_init(). sock_init() performs the following actions, and does not return until complete (or an error was encountered):

Calls subsystem initialization for ARP, TCP, UDP and DNS (if applicable). Tests to see whether sock_init() was run previously. If so, then it returns OK. Otherwise, the following steps are executed.

Initialize the packet driver; basically this resets the hardware and clears out the packet
receive buffer pool.

Clears the router and other server tables. When using Ethernet, waits for approximately 1 second for the Ethernet hardware to initialize. This delay is required since some 10/100Mbit hubs take this long to negotiate.

Interfaces are initialized using the settings specified in the IFCONFIG_* macros or predefined configurations.

If USE_DHCP is specified, DHCP configuration is completed. This may take a second or


so since network traffic needs to flow between the controller board and a DHCP server.

Chapter 2: TCP/IP Initialization

If all of the above completed successfully, the return code is set to 0. Otherwise, the return code will be non-zero, however you can still proceed if the return code is 2 since this indicates that DHCP failed but fallbacks were used. Other return codes indicate that the network is not usable. After sock_init() returns OK, the non-PPPoE Ethernet interface should be ready for traffic if it is intended to be up initially. PPP interfaces may not be fully started even if requested to be up initially. PPP interfaces can take a substantial amount of time to come up, especially if modem dial-out is in use. You can wait for a particular interface to come up by polling the interface status using ifstatus() or, preferably, ifpending().

2.2 Interface Configuration


Prior to Dynamic C version 7.30, only a single network interface was supported. Configuration of the interface was performed by defining a set of macros, such as MY_IP_ADDRESS, as well as by calling various configuration functions such as sethostid(). With version 7.30s support of multiple interfaces, the macro-style configuration becomes impractical, and the configuration functions generally would require an additional parameter, the interface number. Version 7.30 implements a slightly different method of configuration, but maintains compatibility with the old style of configuration for simple applications that require only a single interface. It is recommended that new applications use the new style of configuration, even if multiple interface support is not required. This will ease the integration of future Dynamic C upgrades.

2.2.1 Configuration Overview


To run the TCP/IP stack, a host (i.e., the controller board) needs to know its unique home IP address for each interface. Interfaces that connect to broadcast networks (i.e., Ethernet) must also have a netmask assigned. The combination of IP address and netmask describes the so-called subnet which is addressable on that interface. The subnet basically describes the community of host addresses which can talk directly to this host, without requiring data to pass through a packet router. Point-to-point links only need an IP address, since there is only one other host by definition. IP address and netmask are the most important configuration items, however many other items are needed for successful networking. For anything but strictly local communication, a router or gateway host must be known. The router has the important task of forwarding messages between the local host and the outside world (i.e., hosts that are not on the local subnet). Routers are associated with particular interfaces. Each interface will generally require a different router, however in the majority of cases only one interface will actually be used to talk to non-local hosts so only one router will be required to service all requests for non-local host addresses. Some of the configuration items are not specific to any particular interface. For example, DNS (Domain Name System) servers are known by their IP address. DNS servers are used to translate human-readable domain names (e.g., www.zworld.com) into machine-readable IP addresses.

TCP/IP Users Manual

2.2.2 Sources of Configuration Information


The Dynamic C TCP/IP stack obtains configuration information from one or more of the following sources:

Use one of the predefined configurations in tcp_config.lib; static or dynamic (new


in version 7.30).

Macro definitions before #use dcrtcp.lib; static configuration. Bootstrap network protocols such as BOOTP and DHCP; dynamic configuration. Runtime function calls such as ifconfig() (version 7.30) and sethostid() (previous versions).

Directed ping IP address assignment (new in version 7.30). Console-based configuration, e.g., zconsole.lib.
As application designer, you have to decide which of these configuration techniques is applicable for your project. Entirely static configuration is typically used for initial application development and testing. Most of the TCP/IP sample programs use static configuration for simplicity in getting started. Applications which are intended for real-world use should allow at least one form of dynamic configuration. The particular form of configuration which is supported will depend on the complexity of the application, as well as the expected network or operational environment in which the application will run. 2.2.2.1 Predefined Configurations Since networking configuration can be fairly complicated, Dynamic C version 7.30 has the concept of canned or predefined configurations. This has the advantage of reducing the number of macro definitions at the top of each TCP/IP program, as well as eliminating the need for copy/paste of a lot of settings from one program to the next. Using the predefined configurations is very easy: simply #define a single macro (called TCPCONFIG) at the top of each program. The macro is defined to an integer, which selects one of the predefined configurations in tcp_config.lib. For example: #define TCPCONFIG 1 #use dcrtcp.lib causes the first predefined configuration to be used. Most of the sample TCP/IP programs will refer to one of the predefined configurations. It is fairly likely (unfortunately) that none of the configurations will work with your network. For example, the default IP address of 10.10.6.100 may not be allowed on your LAN. If this is the case, you can modify tcp_config.lib to fix this so it works in your environment. Having fixed it once, all of the sample programs should work, since they all pull the same definitions out of tcp_config.lib. The disadvantage of modifying tcp_config.lib is that any changes you make may be overwritten if you install a new release of Dynamic C. If this is a problem, then there is a solution: you can create a new library called custom_config.lib. In this library, you can place your own custom configurations which will not be overwritten by Dynamic C (since this is not a released library).

Chapter 2: TCP/IP Initialization

To create custom_config.lib, you can use tcp_config.lib as a template. Modify the definitions to suit your network environment. You must change the configuration numbers to be greater than or equal to 100. Numbers less than 100 are expected to be in tcp_config.lib; numbers over 99 cause custom_config.lib to be included. The other thing you must do before using your own custom configurations is to add the library name (custom_config.lib) to the LIB.DIR file in the base Dynamic C installation directory. This is just a text file, which you can edit with the Dynamic C text editor. Locate the line that contains tcp_config.lib. Repeat this line, and modify one of the line copies to point to your custom_config.lib file. You will not have to restart Dynamic C for this change to take effect. A new release of Dynamic C will overwrite the LIB.DIR file, so you will need to perform this edit for each release. To use custom configurations that you define, the only thing necessary in each sample program is to change the definition of the TCPCONFIG macro to indicate the appropriate configuration e.g., #define TCPCONFIG 100 #use dcrtcp.lib 2.2.2.2 Static Configuration This is conceptually the easiest means of configuration; however it is primarily suitable for testing purposes (or possibly as a fallback in case other configuration techniques do not yield a result in a reasonable amount of time). Prior to version 7.30, the (only) interface was configured by defining a fixed set of macros before including dcrtcp.lib. The most common definitions were limited to: MY_IP_ADDRESS, MY_NETMASK, MY_GATEWAY and MY_NAMESERVER. At runtime, the functions, tcp_config(), sethostid() and sethostname() override the configuration macros. Version 7.30 still allows use of these macros for backwards compatibility, however, it is recommended that the new style of static configuration be used for new applications. The new configuration style uses macros called IFCONFIG_*, where * is replaced by the interface name e.g., IFCONFIG_ETH0 for the first Ethernet port. IFCONFIG_ALL contains configuration items which are not specific to any particular interface. The value of the IFCONFIG_* macro is actually a list of items in the syntactic form of a C parameter list. For example, if the old style configuration (for Ethernet) was #define MY_IP_ADDRESS 10.10.6.100 #define MY_NETMASK 255.255.255.0 #define MY_GATEWAY 10.10.6.1 then the new replacement would be #define IFCONFIG_ETH0 \ IFS_IPADDR, aton(10.10.6.100), \ IFS_NETMASK, aton(255.255.255.0), \ IFS_ROUTER_SET, aton(10.10.6.1), \ IFS_UP
10 TCP/IP Users Manual

The replacement looks more complex, but this is because the macro value must be valid C syntax for a parameter list. The IFS_UP parameter at the end of the above example is a new feature for interfaces: they can be dynamically brought up and down. The default state for an interface is down, which is why an explicit IFS_UP is required. The backslashes at the end of each line are used to continue the macro definition over more than one line. The format of the static initialization macros will make more sense if you examine the documentation for the ifconfig() function. You will see that the macro definition is merely plugged in to the parameter list for an ifconfig() call. 2.2.2.3 Dynamic Configuration via the Network The Dynamic C TCP/IP stack supports DHCP (Dynamic Host Configuration Protocol) or BOOTP (Bootstrap Protocol) for dynamic configuration. DHCP is a more modern replacement for BOOTP, which was originally designed to support bootstrap of diskless workstations. Use of these protocols can completely eliminate the need for static configuration. The library BOOTP.LIB allows a target board to be a BOOTP or DHCP client. The protocol used depends on what type of server is installed on the local network. BOOTP and DHCP servers are usually centrally located on a local network and operated by the network administrator. Note that initialization may take longer when using DHCP as opposed to static configuration, but this depends on your server. Both protocols allow a number of configuration parameters to be sent to the client, including:

clients IP address. net mask. list of gateways. host and default domain names. list of name servers.

BOOTP assigns permanent IP addresses. DHCP can lease an IP address to a host, i.e., assign the IP address for a limited amount of time. There are two user-callable functions regarding IP address leases dhcp_release() and dhcp_acquire()(described in Chapter 7). In addition, there are a number of macros and global variables available for modifying behavior and obtaining information. Please see Section 2.5.3 and Section 2.5.4 for details. As of 7.30, DHCP or BOOTP can be used only on the default interface i.e., the interface which is specified by the value of the IF_DEFAULT macro. If you are using more than one interface then you should ensure that IF_DEFAULT is set correctly. To successfully use DHCP configuration, ensure all of the following conditions are met. (Only the first condition applies prior to 7.30.)

#define USE_DHCP before including dcrtcp.lib. Ensure IF_DEFAULT is indicating the desired interface. Define an IFCONFIG_* macro to include the IFS_DHCP parameter ID.

Chapter 2: TCP/IP Initialization

11

For example, if the Ethernet interface is to be used for DHCP, the following code is required for DHCP: #define USE_DHCP #define IF_DEFAULT 0 // not necessary unless also using PPP #define IFCONFIG_ETH0 IFS_DHCP, 1, IFS_UP #use dcrtcp.lib You may also use the predefined configuration number 3, which is DHCP: #define TCPCONFIG 3 #use dcrtcp.lib This configuration sets all required macros for DHCP (or BOOTP) to work. Naturally, there must be a DHCP server available on the interface. The DHCP server must be set up to contain all the required configuration options, however setting up the DHCP server is outside the scope of this document, since there are many different DHCP servers in use. The sample program Samples\tcpip\dhcp.c uses dynamic configuration in a basic TCP/IP program that will initialize the TCP/IP interface, and allow the device to be 'pinged' from another computer on the network. It demonstrates DHCP features, such as releasing and re-acquiring IP addresses and downloading a configuration file. 2.2.2.4 Runtime Configuration using ifconfig() ifconfig() is a function introduced in version 7.30. This function does many things, and is the recommended replacement for some of the functions marked as deprecated (including tcp_config()). ifconfig() performs most of the work for all the other configuration techniques. For example, static configuration (via the IFCONFIG_* macros) basically calls ifconfig() with the specified parameters substituted in. ifconfig() takes a variable number of parameters, like printf(), however the parameter list is terminated with the special IFS_END symbol. For example, to use ifconfig() to set the same parameters as described above for the static configuration: ifconfig(IF_ETH0, IFS_IPADDR, aton(10.10.6.100), IFS_NETMASK, aton(255.255.255.0), IFS_ROUTER_SET, aton(10.10.6.1), IFS_UP, IFS_END); Note that this is the same as substitution of the IFCONFIG_* macro e.g., ifconfig(IF_ETH0, IFCONFIG_ETH0, IFS_END); ifconfig() is also used to obtain current configuration items at runtime e.g., longword ipaddr; ifconfig(IF_ETH0, IFG_IPADDR, &ipaddr, IFS_END); gets the current IP address of the first Ethernet interface into the variable ipaddr. The first parameter of ifconfig() is the interface number. For certain settings, this can also be IF_ANY, which means apply the settings to all applicable interfaces. The parameters following
12 TCP/IP Users Manual

the first are an arbitrary number of tuples consisting of a parameter identifier followed by the value(s) for that parameter (if any). The list of parameters must be terminated by a special identifier, IFS_END. See the documentation for ifconfig() for a complete list of parameter identifiers with their expected values. 2.2.2.5 Directed Ping This style of configuration, also known as ICMP configuration, is limited to setting the IP address of the interface. It only works on non-PPPoE Ethernet interfaces. To specify directed ping configuration, use the IFS_ICMP_CONFIG parameter ID in a call to ifconfig() or in the definition of the IFCONFIG_* macro for the interface. For example #define IFCONFIG_ETH0 IFS_ICMP_PING, 1 for a static configuration, or ifconfig(IF_ETH0, IFS_ICMP_CONFIG, 1, IFS_END); at runtime. Note that you can use both directed ping and DHCP on the same interface, but directed ping is not limited to just the default interface. If both directed ping and DHCP are allowed on a particular interface, the first one wins. Directed ping works as follows. The interface is brought up, but has no assigned IP address so it cannot be used for normal traffic. If the interface receives an ICMP echo request (i.e., ping) which is directed to the interfaces MAC address, then the destination IP address in the ICMP packet is assigned to the interface as its home IP address. After that point, the interface is configured and is available for normal traffic. The weakness of directed ping is that only the IP address is provided. The netmask must be preconfigured or obtained by other means. Technically, directed ping violates some tenets of the Internet standards, however, it can be useful in controlled environments. In order for directed ping to work, the MAC address of the board must be known (see below). The host which initiates the ICMP echo request must have its ARP table statically configured with the target MAC address. On Unix and Windows hosts, the appropriate command sequence is arp -s <IP address> <MAC address> followed by ping <IP address> The actual format of the MAC address depends on the operating system. Most hosts will recognize a format like 00-09-A0-20-00-99. The IP address is in dotted decimal notation. Once the interface is configured by directed ping (or DHCP), then further directed ping or DHCP configurations for that interface are not allowed. If desired, at runtime you can issue ifconfig(IF_ETH0, IFS_ICMP_CONFIG_RESET, IFS_END); to allow another directed ping configure.

Chapter 2: TCP/IP Initialization

13

2.2.2.6 Console Configuration via Zconsole.lib The zconsole.lib library contains routines for allowing an external (serial or telnet) terminal to issue configuration commands. Basically, the commands call ifconfig() to perform the actual requests or obtain information. Using a dumb terminal connection over a serial port presents no special difficulties for network configuration. Using telnet over the internet obviously requires a working TCP stack to begin with. This is still useful in the case that one of the other configuration techniques can at least get to a working state. For example, directed ping can assign an IP address. You could then use the same host to telnet into the new IP address in order to set other items like the netmask and router. 2.2.2.7 Media Access Control (MAC) address Rarely, ISPs require that the user provide them with a MAC address for their device. Run the utility program, Samples\tcpip\display_mac.c, to display the MAC address of your controller board. The MAC address is also required for directed PING configure, as well as some other bootstrap techniques. MAC addresses are often written as a sequence of six two-digit hexadecimal numbers, separated by colons e.g., 00:90:20:33:00:A3. This distinguishes them from IP addresses, which are written with dotted decimal numbers. MAC addresses are completely unrelated to IP addresses. IP addresses uniquely identify each host on the global Internet. MAC addresses uniquely identify Ethernet hardware on a particular Ethernet LAN segment. Although only technically required to be unique on a LAN segment, in practice MAC addresses are globally unique and can thus be used to uniquely identify a particular Ethernet adapter. The usual reason for an ISP requiring a MAC address is if the ISP uses DHCP to dynamically assign IP addresses. Most ISPs use PPP (Point to Point Protocol) which does not care about MAC addresses. DHCP can use the MAC address to determine that the same device is connecting, and assign it the same IP address as before.

14

TCP/IP Users Manual

2.3 Dynamically Starting and Stopping Interfaces


Dynamic C version 7.30 allows interfaces to be individually brought up and down by calling the ifup(), ifdown() or ifconfig() functions. The initial desired state of the interface is specified using the IFCONFIG_* macros. By default, interfaces are not brought up when sock_init() is called at boot time. Only if the IFCONFIG_* macro contains an IFS_UP directive will the interface will be brought up at boot time. Most applications should not need to dynamically change the interface status. The exception to this may be PPP over serial interfaces, where a modem is used to dial out to an ISP on demand.

2.3.1 Testing Interface Status


There are two functions for testing the current status of an interface: ifstatus() and ifpending(). The function ifstatus() merely returns a boolean value indicating whether the interface is up. If the return value is true (non-zero), then the interface is ready for normal TCP/IP communications. Otherwise, the interface is not yet available; it may either be down, or in the process of coming up. ifpending() gives more information: its return value indicates not only the current state, but also if the state is in the process of changing. If your application needs to check the interface status, which is recommended for PPP over serial or PPPoE, then it can either poll the status using the above functions, or it can register a callback function which is automatically called whenever the interface changes status. To register a callback function, you call ifconfig() with the IFS_IF_CALLBACK as the parameter identifier, and the address of your callback function as the parameter value.

2.3.2 Bringing an Interface Up


You can call ifup(), or ifconfig() with the IFS_UP parameter identifier. The advantage of using ifconfig() is that you can specify an interface number of IF_ANY, which brings all interfaces up together. When the ifup() call returns, the interface may not have completed coming up. This is notably the case for PPP interfaces, which require a number of protocol negotiation packets to be sent and received. In addition, PPP over serial may require additional time to reset a modem, dial out to an ISP, and possibly respond to the ISPs login procedure. All this could take considerable time, so the ifup() function does not wait around for the process to complete, to allow the application to proceed with other work. On return from the ifup() call, an application must test for completion using the functions described in the previous section.

Chapter 2: TCP/IP Initialization

15

In order for the interface to come up completely, your application must call tcp_tick() regularly while waiting for it. If you can afford to block until the interface is up, then use code similar to the following: ifup(IF_PPP2); // Wait for the interface to have any status other than down coming up. while (ifpending(IF_PPP2) == 1) tcp_tick(); if (ifstatus(IF_PPP2)) printf(PPP2 is up now.\n); else printf(PPP2 failed to come up.\n);

2.3.3 Bringing an Interface Down


You can call ifdown(), or ifconfig() with the IFS_DOWN parameter identifier. The advantage of using ifconfig() is that you can specify an interface number of IF_ANY, which brings all interfaces down together. As for ifup(), ifdown() does not necessarily complete immediately on return. PPP requires link tear-down messages to be sent to the peer and acknowledged. Thus, similar considerations apply to bringing an interface down as they do for bringing it up. ifdown() will always succeed eventually. Unlike ifup(), which can possibly fail to bring the interface up, ifdown() will always eventually return success i.e., it is not possible for an interface to be left hanging up. If the PPP link tear-down does not get an acknowledgment from the peer, then the process times out and the link is forced down.

16

TCP/IP Users Manual

2.4 Setting up PPP Interfaces


PPP interfaces are slightly more complicated to configure than non-PPPoE Ethernet. They also generally take more time to become established. The advantage of PPP is that it can be made to run over a wide variety of physical layer hardware: on Rabbit-based boards this includes the asynchronous serial ports, as well as Ethernet (using PPPoE). Use of PPP over asynchronous serial allows boards with no Ethernet hardware to communicate using TCP/IP protocols. Starting with Dynamic C version 7.30, the process of establishing a PPP link has been more tightly integrated into the library (using the ifup()/ifdown()/ifconfig() functions). Prior to 7.30, your application had to be hard-coded to use either Ethernet, PPP or PPPoE. Chapter 18 explains the details of establishing PPP interfaces. The following sections provide an overview.

2.4.1 PPP over Asynchronous Serial


There are two basic scenarios for use of PPP over asynchronous serial (shortened here to just PPP). The first is a direct, hard-wired, connection to another machine. The second is a connection to an ISP (Internet Service Provider) via a modem. Modem connections introduce another layer of complexity in that the modem itself must be instructed to connect to the desired peers modem, most often via the PSTN (Public Switched Telephone Network). Most often, ISPs also have special requirements for establishing PPP links which are often unrelated to PPP itself. For example, many ISPs require navigation of login scripts which are basically intended for human users. With hard-wired connections, e.g., RS232 cables with null modems or crossed-over connections, the process of establishing a PPP link is relatively simple and reliable. Bringing such a PPP link up involves opening the serial port, sending and receiving PPP link negotiation messages (known as LCP; Link Control Protocol), sending and receiving authentication messages (PAP; Password Authentication Protocol) then finally sending and receiving Internet Protocol Control Messages (IPCP). If all negotiations are successful, the link is then ready for TCP/IP traffic. If the link is established via a modem, then an extra layer of activity must precede the initial PPP negotiation. This is outside the scope of PPP, since it is really related to the establishment of a physical layer. The TCP/IP library gives you the option of incorporating the modem connection phase into the process of bringing the interface up and down. If preferred, the modem phase can be performed entirely separately from the ifup()/ifdown() process. This may be necessary if there are special requirements for connecting to the ISP.

2.4.2 PPP over Ethernet


PPPoE is often considered a hack. It seems superfluous to define a protocol that establishes a logical connection between two peers on what is otherwise a broadcast (i.e., any-to-any) medium. Nevertheless, the existence of PPPoE was largely dictated by the needs of ISPs who wished to continue using their existing infrastructure, based on the earlier generation of dial-in connections. The advent of high speed (ADSL etc.) modems, that had an Ethernet connection to the users network, made PPPoE an attractive proposition. If your application requires connection to an ISP via an ADSL modem, then you will most likely need to support PPPoE. PPPoE also requires a physical layer negotiation to precede the normal PPP negotiations. This is known as the access concentrator discovery phase (discovery for short). PPPoE makes a disChapter 2: TCP/IP Initialization 17

tinction between PPPoE servers and PPPoE clients, however, PPP makes no distinction; you can think of PPP as also standing for Peer to Peer Protocol. The PPPoE server is known as the access concentrator. The Dynamic C TCP/IP libraries do not support acting as the access concentrator; only the PPPoE client mode is supported. This is the most common case, since the DSL modem is always configured as an access concentrator.

2.5 Configuration Macro Reference


This section categorizes the configuration macros by their purpose.

2.5.1 Removing Unnecessary Functions


The following macros default to being undefined (i.e., the functionality is included by default). You can define one or more of these macros to free up code and data memory space.

DISABLE_DNS
This macro disables DNS lookup. This prevents a UDP socket for DNS from being allocated, thus saving memory. Users may still call resolve() with an IP address, provided that the address is in dotted decimal form i.e., does not require a real DNS lookup.

DISABLE_UDP
This macro disables all UDP functionality, including DNS, SNMP, TFTP and DHCP/BOOTP. You can define this to save a small amount of code if your application only needs to be a TCP server, or a TCP client that does not need to do name lookups. This macro is available starting with Dynamic C 7.30.

DISABLE_TCP
This macro disables all TCP functionality, including HTTP (web server), SMTP (mail) and other TCP-based protocols. You can define this to save a substantial amount of code if your application only needs UDP. This macro is available starting with Dynamic C 7.30.

2.5.2 Including Additional Functions


The following macros default to being undefined i.e., the functionality is not included by default.

USE_DHCP
This macro is required when DHCP or BOOTP functionality is desired.

USE_SNMP
Define this to be the version number of SNMP (Simple Network Management Protocol) to be supported. Currently, the only allowable value is 1.

USE_MULTICAST
This macro will enable multicast support. In particular, the extra checks necessary for accepting multicast datagrams will be enabled and joining and leaving multicast groups (and informing the Ethernet hardware about it) will be added.
18 TCP/IP Users Manual

USE_IGMP
If this macro is defined, the USE_MULTICAST macro is automatically defined. This macro enables sending reports on joining multicast addresses and responding to IGMP queries by multicast routers. Unlike USE_MULTICAST, this macro must be defined to be 1 or 2. This indicates which version of IGMP will be supported. Note, however, that both version 1 and 2 IGMP clients will work with both version 1 and 2 IGMP routers. Most users should just choose version 2.

2.5.3 BOOTP/DHCP Control Macros


Various macros control the use of DHCP. Apart from setting these macros before '#use dcrtcp.lib', there is typically very little additional work that needs to be done to use DHCP/BOOTP services. Most of the work is done automatically when you call sock_init() to initialize TCP/IP. There are more control macros available than what are listed here. Please look at the beginning of the file lib\tcpip\bootp.lib for more information.

USE_DHCP
If this macro is defined, the target uses BOOTP and/or DHCP to configure the required parameters. This macro must be defined to use DHCP services.

DHCP_USE_BOOTP
If defined, the target uses the first BOOTP response it gets. If not defined, the target waits for the first DHCP offer and only if none comes in the time specified by _bootptimeout does it accept a BOOTP response (if any). Use of this macro speeds up the boot process, but at the expense of ignoring DHCP offers if there is an eager BOOTP server on the local subnet.

DHCP_CHECK
If defined, and USE_DHCP is defined, then the target will check for the existence of another host already using an offered IP address, using ARP. If the host exists, then the offer will be declined. If this happened most DHCP servers would log a message to the administrator, since it may represent a misconfiguration. If not defined, then the target will request the first offered address without checking.

DHCP_CLASS_ID Rabbit2000-TCPIP:Z-World:Test:1.0.0
This macro defines a class identifier by which the OEM can identify the type of configuration parameters expected. DHCP servers can use this information to direct the target to the appropriate configuration file. Z-World recommends the standard format: hardware:vendor:product code:firmware version.

DHCP_USE_TFTP
If this and USE_DHCP are defined, the library will use the BOOTP filename and server to obtain an arbitrary configuration file that will be accessible in a buffer at physical address _bootpdata, with length, _bootpsize. The global variables, _bootpdone and _bootperror indicate the status of the boot file download. DHCP_USE_TFTP should be defined to the maximum file size that may be downloaded.
Chapter 2: TCP/IP Initialization 19

DHCP_CLIENT_ID clientid_char_ptr DHCP_CLIENT_ID_LEN clientid_length


Define a client identifier string. Since the client ID can contain binary data, the length of this string must be specified as well. This string MUST be unique amongst all clients in an administrative domain, thus in practice the client ID must be individually set for each client e.g., via front-panel configuration. It is NOT recommended to program a hard-coded string (as for class ID). Note that RFC2132 recommends that the first byte of the string should be zero if the client ID is not actually the hardware type and address of the client (see next).

DHCP_CLIENT_ID_MAC
If defined, this overrides DHCP_CLIENT_ID, and automatically sets the client ID string to be the hardware type (1 for Ethernet) and MAC address, as suggested by RFC2132.

2.5.4 BOOTP/DHCP Global Variables


The following list of global variables may be accessed by application code to obtain information about DHCP or BOOTP. These variables are only accessible if USE_DHCP is defined. The variables marked "deprecated" should be accessed using ifconfig(IF_DEFAULT,...) as noted, rather than directly accessed.

_bootpon (Deprecated)
Runtime control of whether to perform DHCP/BOOTP. This is initially set to 'true.' It can be set to false before calling sock_init (the function that initializes the TCP/IP stack), causing static configuration to be used. Static configuration uses the values defined for the configuration macros, MY_IP_ADDRESS etc. If BOOTP fails during initialization, this will be reset to 0. If reset, then you can call dhcp_acquire() at some later time.
NOTE: Starting with Dynamic C 7.30, it is recommended that you do not manipulate

this flag. Use ifconfig() instead to set the DHCP status for the default interface, using the IFS_DHCP/IFG_DHCP parameter.

_survivebootp (Deprecated)
Set to one of the following values: 0: If BOOTP/DHCP fails, then a runtime error occurs. This is the default. 1: If BOOTP fails, then use the values in MY_IP_ADDRESS etc. If those macros are not defined, a runtime error occurs.
NOTE: Starting with Dynamic C 7.30, it is recommended that you do not manipulate

this flag. Use ifconfig() with the IFS_DHCP_FALLBACK parameter.

_dhcphost
IP address of last-used DHCP server (~0UL if none). If _survivebootp is true, then this variable should be checked to see if DHCP/BOOTP was actually used to obtain the lease. If _dhcphost is ~0UL, then the fallback parameters (MY_IP_ADDRESS etc.) were used since no DHCP server responded.
20 TCP/IP Users Manual

_bootphost
IP address of the last-used BOOTP/TFTP server (~0UL if none). Usually obtained from the siaddr field of the DHCP OFFER/ACK message. This is the default host used if NULL is given for the hostname in the call to tftp_exec(). This is the host that provides the boot file.

_dhcplife, _dhcpt1, _dhcpt2


These variables contain various absolute time values (referenced against SEC_TIMER) at which certain aspects of the DHCP protocol get activated. _dhcplife is when the current lease expires. If _dhcplife is ~0UL (i.e., 0xFFFFFFFF) then the lease is permanent and the other variables are not used. Otherwise, _dhcpt1 is when the current lease must be renewed by the current DHCP server. _dhcpt2 is when the lease must be re-bound to a possibly different server, if the current server does not respond. In general, _dhcpt1 < _dhcpt2 < _dhcplife. To work out the number of seconds remaining until the current lease expires, use code similar to if (_dhcplife == ~0UL) printf("Lease is permanent\r\n"); else if (_dhcplife > SEC_TIMER) printf("Remaining lease %lu seconds\r\n", _dhcplife - SEC_TIMER); else printf("Lease is expired\r\n");

_bootptimeout (Deprecated)
Number of seconds to wait for a BOOTP or DHCP offer. If there is no response within this time (default 30 seconds), then BOOTP is assumed to have failed, and the action specified by _survivebootp will be taken. You can set this variable to a different value before calling sock_init().
NOTE: Starting with Dynamic C 7.30, it is recommended that you do not manipulate this flag. Use ifconfig() with the IFS_DHCP_TIMEOUT parameter.

_bootpdone
Is set to a non-zero value when TFTP download of the boot file is complete. This variable only exists if DHCP_USE_TFTP is defined. It is set to one of the following values: 0: Download not complete, or boot file not yet known. 1: Boot file download completed (check _bootperror for status). 2: No boot file was specified by the server.

_bootpsize
Indicates how many bytes of the boot file have been downloaded. Only exists if DHCP_USE_TFTP is defined.

Chapter 2: TCP/IP Initialization

21

_bootpdata
Physical starting address of boot data. The length of this area will be DHCP_USE_TFTP bytes, however, the actual amount of data in the buffer is given by _bootpsize. This variable only exists if DHCP_USE_TFTP is defined and is only valid if _bootpdone is 1. You can access the data using xmem2root() and related functions.

_bootperror
Indicates any error which occurred in a TFTP process. This variable only exists if DHCP_USE_TFTP is defined and is only valid when _bootpdone is 1. _bootperror is set to one of the following values (which are also documented with the tftp_tick() function): 0: No error. -1: Error from boot file server, transfer terminated. This usually occurs because the server is not configured properly, and has denied access to the nominated file. -2: Error, could not contact boot file server or lost contact. -3: Timed out, transfer terminated. -4: (not used) -5: Transfer complete, but truncated because buffer too small to receive the complete file.

_smtpsrv
IP address of mail server, or 0 if not obtained.

2.5.5 Buffer and Resource Sizing MAX_SOCKETS (deprecated)


This macro defines the number of sockets that will be allocated, not including the socket for DNS lookups. It defaults to 4. If libraries such as HTTP.LIB or FTP_SERVER.LIB are used, you must provide enough sockets in MAX_SOCKETS for them also. This macro has been replaced by MAX_TCP_SOCKET_BUFFERS and MAX_UDP_SOCKET_BUFFERS.

MAX_SOCKET_LOCKS
For C/OS-II support. This macro defines the number of socket locks to allocate. It defaults to MAX_TCP_SOCKET_BUFFERS + MAX_UDP_SOCKET_BUFFERS. This macro is necessary because we can no longer calculate the number of socket locks needed based on the number of socket buffers, now that the user can manage their own socket buffers.

MAX_TCP_SOCKET_BUFFERS
Starting with Dynamic C version 7.05, this macro determines the maximum number of TCP sockets with preallocated buffers. If MAX_SOCKETS is defined, then MAX_TCP_SOCKET_BUFFERS will be assigned the value of MAX_SOCKETS for
22 TCP/IP Users Manual

backwards compatibility. If neither macro is defined, MAX_TCP_SOCKET_BUFFERS defaults to 4.

MAX_UDP_SOCKET_BUFFERS
Starting with Dynamic C version 7.05, this macro determines the maximum number of UDP sockets with preallocated buffers. It defaults to 0.

SOCK_BUF_SIZE (deprecated)
This macro determines the size of the socket buffers. A TCP socket will have two buffers of size SOCK_BUF_SIZE/2 for send and receive. A UDP socket will have a single buffer of size SOCK_BUF_SIZE. Both types of sockets take the same total amount of buffer space. This macro has been replaced by TCP_BUF_SIZE and UDP_BUF_SIZE.

TCP_BUF_SIZE
Starting with Dynamic C 7.05, TCP and UDP socket buffers are sized separately. TCP_BUF_SIZE defines the buffer sizes for TCP sockets. It defaults to 4096 bytes. Backwards compatibility exists with earlier version of Dynamic C: if SOCK_BUF_SIZE is defined, TCP_BUF_SIZE is assigned the value of SOCK_BUF_SIZE. If SOCK_BUF_SIZE is not defined, but tcp_MaxBufSize is, then TCP_BUF_SIZE will be assigned the value of tcp_MaxBufSize*2.

tcp_MaxBufSize (deprecated)
This use of this macro is deprecated in Dynamic C version 6.57 and higher; it has been replaced by SOCK_BUF_SIZE. In Dynamic C versions 6.56 and earlier, tcp_MaxBufSize determines the size of the input and output buffers for TCP and UDP sockets. The sizeof(tcp_Socket) will be about 200 bytes more than double tcp_MaxBufSize. The optimum value for local Ethernet connections is greater than the Maximum Segment Size (MSS). The MSS is 1460 bytes. You may want to lower tcp_MaxBufSize, which defaults to 2048 bytes, to reduce RAM usage. It can be reduced to as little as 600 bytes. tcp_MaxBufSize will work slightly differently in Dynamic C versions 6.57 and higher. In these later versions the buffer for the UDP socket will be tcp_MaxBufSize*2, which is twice as large as before.

UDP_BUF_SIZE
Starting with Dynamic C 7.05, TCP and UDP socket buffers are sized separately. UDP_BUF_SIZE defines the buffer sizes for UDP sockets. It defaults to 4096 bytes. Backwards compatibility exists with earlier version of Dynamic C: if SOCK_BUF_SIZE is defined, UDP_BUF_SIZE is assigned the value of SOCK_BUF_SIZE. If SOCK_BUF_SIZE is not defined, but tcp_MaxBufSize is, then UDP_BUF_SIZE will be assigned the value of tcp_MaxBufSize*2.

Chapter 2: TCP/IP Initialization

23

ETH_MTU
Define the Maximum Transmission Unit for Ethernet and PPPoE interfaces. The default is 600, but may be increased to a maximum of 1500 subject to root data memory limitations. PPPoE always uses a value that is 8 less than this figure. For maximum throughput on an Ethernet link, use the largest value (1500). Note that, in DC version 7.30, a macro will be defined which is set to the larger of ETH_MTU and PPP_MTU. This macro is called MAX_MTU, and is used for sizing the receive buffer for incoming packets from all interfaces.

PPP_MTU
Define the maximum transmission/receive unit for PPP over serial links. This defaults to the same as ETH_MTU if it is defined, or 600. This macro is new for 7.30.

ETH_MAXBUFS
Define the maximum number of incoming packets that may be buffered. Defaults to 10. The buffers are shared between all interfaces (in spite of the name). The total amount of root data storage for incoming packets depends on the configured mix of interface types, but is (MAX_MTU+22)*ETH_MAXBUFS for just Ethernet without PPPoE. This will default to 6220 bytes if the defaults are selected.

ARP_TABLE_SIZE
Define to the number of ARP table entries. The default is set to the number of interfaces, plus 5 entries for every Ethernet interface (excluding PPPoE). The maximum allowable value is 200.

ARP_ROUTER_TABLE_SIZE
Define the maximum number of routers. Defaults to the number of interfaces, plus an extra entry for each Ethernet (excluding PPPoE) .

MAX_STRING
Define the maximum number of characters for a hostname or for a mail server when using the function smtp_setserver(). Defaults to 50.

MAX_NAMESERVERS
Define the maximum number of DNS servers. Defaults to 2.

MAX_COOKIES
Define the maximum number of cookies that a server can send to or receive from a client. Defaults to 1.

TCP_MAXPENDING
Define the maximum number of pending TCP connections allowed in the active list. Defaults to 20.

24

TCP/IP Users Manual

MAX_RESERVEPORTS
Defines the maximum number of TCP port numbers that may be reserved. Defaults to 5 if USE_RESERVEDPORTS is defined (which is defined by default). For more information about USE_RESERVEDPORTS and setting up a listen queue, please see Section 3.3.4.

DNS_MAX_RESOLVES
4 by default. This is the maximum number of concurrent DNS queries. It specifies the size of an internal table that is allocated in xmem.

DNS_MAX_NAME
64 by default. Specifies the maximum size in bytes of a host name that can be resolved. This number includes any appended default domain and the NULL-terminator. Backwards compatibility exists for the MAX_DOMAIN_LENGTH macro. Its value will be overridden with the value DNS_MAX_NAME if it is defined. For temporary storage, a variable of this size must be placed on the stack in DNS processing. Normally, this is not a problem. However, for C/OS-II with a small stack and a large value for DNS_MAX_NAME, this could be an issue.

DNS_MAX_DATAGRAM_SIZE
512 by default. Specifies the maximum length in bytes of a DNS datagram that can be sent or received. A root data buffer of this size is allocated for DNS support.

DNS_SOCK_BUF_SIZE
1024 by default. Specifies the size in bytes of an xmem buffer for the DNS socket. Note that this means that the DNS socket does not use a buffer from the socket buffer pool.

2.5.6 Pre Version 7.30 Network Configuration


These macros should only be used for releases of Dynamic C prior to version 7.30. They are supported in 7.30 for backward compatibility, however new applications should use the new style of configuration outlined in the next section. Use of the runtime functions mentioned in this section is deprecated in favor of ifconfig().

MY_DOMAIN
This macro is the initial value for the domain portion of the controllers address. At runtime, it can be overwritten by tcp_config() and setdomainname().

MAX_DOMAIN_LENGTH
Specify the maximum domain name length, including any concatenated host name. Defaults to 128.

MY_GATEWAY
This macro gives the default value for the controllers default gateway. At runtime, it can be overwritten by tcp_config().

Chapter 2: TCP/IP Initialization

25

MY_IP_ADDRESS
This macro is the default IP address for the controller. At runtime, it can be overwritten by tcp_config() and sethostid().

MY_NAMESERVER
This macro is the default value for the primary name server. At runtime, it can be overwritten by tcp_config().

MY_NETMASK
This macro is the default netmask for the controller. At runtime, it can be overwritten by tcp_config().

2.5.7 Version 7.30 Interface Configuration TCPCONFIG


Define to the number of a predefined configuration in tcp_config.lib (numbers less than 100) or custom_config.lib (numbers greater or equal to 100). Defaults to 0, which means no predefined configuration.

USE_ETHERNET
Define to 0 (or leave undefined) if Ethernet is not required. Define to 1 if the first Ethernet port is to be used. Defaults to 0. This macro does not include PPPoE interfaces.

USE_PPP_SERIAL
Define to a bitwise-OR combination of

0x01 - Serial port A (IF_PPP0) 0x02 - Serial port B (IF_PPP1) 0x04 - Serial port C (IF_PPP2) 0x08 - Serial port D (IF_PPP3)

Defaults to 0, i.e., no PPP over serial.

USE_PPPOE
Define in the same way as USE_ETHERNET, except that PPPoE is used on the specified Ethernet port. Defaults to 0 i.e., no PPPoE interfaces.

26

TCP/IP Users Manual

IFCONFIG_ALL IFCONFIG_DEFAULT IFCONFIG_ETH0 IFCONFIG_PPP0..5 IFCONFIG_PPPOE0


All the above IFCONFIG_* macros are defined in a similar manner. IFCONFIG_ALL is reserved for configuration items that are not specific to any particular interface number. IFCONFIG_DEFAULT is applied to the default interface (IF_DEFAULT) if there is no specific IFCONFIG_* for the default interface. These macros must be defined as a C parameter list fragment. This is because the macro value is substituted into a call to ifconfig() at initialization time (sock_init()). For example, the fragment of code that initializes the non-PPPoE Ethernet interface looks somewhat like the following: #ifdef IF_ETH0 #ifdef IFCONFIG_ETH0 ifconfig(IF_ETH0, IFCONFIG_ETH0, IFS_END); #else #if IF_DEFAULT == IF_ETH0 ifconfig(IF_DEFAULT, IFCONFIG_DEFAULT, IFS_END); #endif #endif #endif The entire fragment is processed only if IF_ETH0 is defined, i.e., you have specified that the non-PPPoE Ethernet interface is to be used. Inside this, if the IFCONFIG_ETH0 macro has been defined, then it is substituted into an ifconfig() call for IF_ETH0. Otherwise, if IF_ETH0 is the default (i.e., equal to IF_DEFAULT) then the IFCONFIG_DEFAULT macro is substituted into the ifconfig() call. Note that for backwards compatibility, IFCONFIG_DEFAULT is always defined to something if it was not explicitly defined prior to inclusion of dcrtcp.lib. It is defined using the given values of the pre version 7.30 macros: MY_IP_ADDRESS, MY_GATEWAY etc. The IFCONFIG_* macros can be defined to be an arbitrary number of ifconfig() parameters. For example, #define IFCONFIG_ETH0\ IFS_IPADDR,aton("10.10.6.100"), \ IFS_NETMASK,0xFFFFFF00uL, \ IFS_ROUTER_ADD,aton("10.10.6.1"), \ IFS_ROUTER_ADD_STATIC,aton("10.10.6.111"), \ aton("10.10.6.0"),0xFFFFFF00uL, \ IFS_DEBUG, 5, \ IFS_ICMP_CONFIG, 1, \ IFS_UP which sets up local IP address and netmask, two routers, turns the verbose level all the
Chapter 2: TCP/IP Initialization 27

way up, allows ping configure, and finally specifies that the interface be brought up at boot time. The final IFS_UP is important: if it is omitted, then the interface will not be brought up at boot time; you will need to call ifup() explicitly after sock_init(). For a full list of the parameters that you can specify in an IFCONFIG_* macro, please see the documentation for the ifconfig() function in Table 4 on page 102.

2.5.8 Time-Outs and Retry Counters RETRAN_STRAT_TIME


This is used for several purposes. It is the minimum time granularity (in milliseconds) of the retransmit process. No time-out is set less than this value. It defaults to 10 ms.

TCP_OPENTIMEOUT
Defines the time-out value (in milliseconds) for active open processing. Defaults to 31000 ms.

TCP_CONNTIMEOUT
Defines the time-out value (in milliseconds) during open or close negotiation. Defaults to 13000 ms.

TCP_SYNQTIMEOUT
Defines the time-out value (in milliseconds) for pending connection. Defaults to 90000 ms.

TCP_TWTIMEOUT
Define time to linger in TIMEWAIT state (milliseconds). It should be from .5 to 4 minutes (2MSL) but it's not really practical for us. Two seconds will hopefully handle the case where ACK must be retransmitted, but can't protect future connections on the same port from old packets. Defaults to 2000 ms.

KEEPALIVE_NUMRETRYS
Number of times to retry the TCP keepalive. Defaults to 4.

KEEPALIVE_WAITTIME
Time (in seconds) to wait for the response to a TCP keepalive. Defaults to 60 seconds.

TCP_MAXRTO
Set an overall upper bound for the retransmit timeout. This is in units of milliseconds. Defaults to 50,000 ms.

28

TCP/IP Users Manual

TCP_MINRTO
Set a lower bound for the retransmit timeout. This is in units of milliseconds. Default is 250 ms ( second). Beware of reducing this, since modern hosts try to ack only every second segment. If our RTO is too small, we will unnecessarily retransmit if we don't get the ack for the first of the two segments (especially on a fast LAN, where the RTT measurement will want to make us set a small time-out).

TCP_LAZYUPD
Set a delay time for "lazy update" (ms). This is used to slightly delay window updates and empty acknowledgments to the peer, in the hope of being able to tag extra data along with otherwise empty segments. This improves performance by allowing better interleaving of application processing with TCP activity, and sending fewer empty segments. This delay interval is also used when we need to retransmit owing to a temporary shortage of Ethernet transmit buffers. Defaults to 5 ms.

DNS_RETRY_TIMEOUT
2000 by default. Specifies the number of milliseconds to wait before retrying a DNS request. If a request to a nameserver times out, then the next nameserver is tried. If that times out, then the next one is tried, in order, until it wraps around to the first nameserver again (or runs out of retries).

DNS_NUMBER_RETRIES
2 by default. Specifies the number of times a request will be retried after an error or a timeout. The first attempt does not constitute a retry. A retry only occurs when a request has timed out, or when a nameserver returns an unintelligible response. That is, if a host name is looked up and the nameserver reports that it does not exist and then the DNS resolver tries the same host name with or without the default domain, that does not constitute a retry.

DNS_MIN_KEEP_COMPLETED
10000 by default. Specifies the number of milliseconds a completed request is guaranteed to be valid for resolve_name_check(). After this time, the entry in the internal table corresponding to this request can be reused for a subsequent request.

2.5.9 Program Debugging TCP_STATS


Enable TCP socket statistics collection. This causes some additional fields to be defined in the TCP socket structure, which are updated with various counters. This is mainly for internal debugging.

DCRTCP_DEBUG
If defined, allow Dynamic C debugging in all TCP/IP libraries. This allows you to trace into library functions in case you are finding difficulty in solving a TCP/IP problem. Remember to remove this definition when compiling for a production environment.

Chapter 2: TCP/IP Initialization

29

DCRTCP_VERBOSE
If defined, enable debugging messages to be printed by the library to the Dynamic C stdout window. This can be very informative when you are trying to see how the TCP/IP libraries work. Unfortunately, the string messages take up a lot of root code space, so you may need to increase the DATAORG value in the BIOS. Otherwise, you can be more selective about which messages are printed by defining *_VERBOSE macros for individual libraries (DCRTCP_VERBOSE merely turns on all the individual library verbose definitions). See dcrtcp.lib source for a listing of the available debug and verbose macros. Note that the number of messages printed depends on the value of a global variable, debug_on. If this variable is 0, only a few messages are printed. If set to higher numbers (up to 5), then successively more detailed messages are printed. You can set this variable directly at the start of your main() function, or preferably use ifconfig(IF_ANY, IFS_DEBUG, 5, IFS_END);

2.5.10 Miscellaneous Macros TCP_FASTSOCKETS


Define to 1 if sockets connected to reserved ports can be closed without the usual 2MSL delay. The default is set to 1, define to 0 to override this.

NET_ADD_ENTROPY
Define this macro to allow network packet arrival times (from any interface) to be a source of random number seeds. See RAND.LIB for further information.

NET_COARSELOCK
This macro is only used when C/OS-II is active. It affects the definition of 2 other macros: LOCK_SOCK(s) and UNLOCK_SOCK(s). If NET_COARSELOCK is not defined, the lock/unlock macros are individual socket locks for use on socket transmit/receive buffers and the socket structure itself. If it is defined, the lock/unlock macros are global locks.

TCP_NO_CLOSE_ON_LAST_READ
If defined, then support half-close; i.e., sock_close() only closes the transmit side of the socket, but allows indefinite receives until the peer closes. This prevents the normal close timeout from being set. Also, when reading, if the socket is half-closed by the peer, then the socket will be automatically closed from this side if this define is not set.

30

TCP/IP Users Manual

2.5.10.1 TOS and TTL TOS and TTL are fields in the IP header. TOS, short for Type of Service, uses 4 bits to specify different types of service. For normal service all 4 bits are zero. Different applications will want different types of service. For example, SNMP might set the maximize reliability bit, whereas FTP would want maximize throughput.

IPTOS_DEFAULT is normal service. IPTOS_CHEAP minimizes monetary cost. IPTOS_RELIABLE maximizes reliability. IPTOS_CAPACIOUS maximizes throughput IPTOS_FAST minimizes delay. IPTOS_SECURE maximizes security.

Note that you may not OR these values together. You must pick one only! TTL, short for Time to Live, specifies how many routers a packet may visit before it is discarded, or how many seconds it can remain in the network, whichever comes first.

TCP_TTL
Default TTL of TCP segments. This value is from Internet STD0002. Defaults to 64.

TCP_TOS
Default type of service for TCP. Defaults to IPTOS_DEFAULT.

UDP_TTL
Default TTL of UDP datagrams. This value is from Internet STD0002. Defaults to 64.

UDP_TOS
Default type of service for UDP. Defaults to IPTOS_DEFAULT.

ICMP_TOS
Default type of service for ICMP. Defaults to IPTOS_DEFAULT.

Chapter 2: TCP/IP Initialization

31

32

TCP/IP Users Manual

3.TCP and UDP Socket Interface


TCP (Transmission Control Protocol) and UDP (User Datagram Protocol) are both transport layer protocols. TCP is used when a reliable, stream-oriented, transport is required for data flowing between two hosts on a network. UDP is a record-oriented protocol which is used when lower overhead is more important than reliability. The acronym UDP is sometimes expanded as unreliable datagram protocol although, in practice, UDP is quite reliable especially over a local Ethernet LAN segment. The Dynamic C TCP/IP libraries implement TCP and UDP over IP (Internet Protocol). IP is a network layer protocol, that in turn uses lower levels known as link layer protocols, such as Ethernet and PPP (Point-to-Point Protocol). The link-layer protocols depend on a physical layer, such as 10BaseT for Ethernet, or asynchronous RS232 for PPP over serial. In the other direction, various protocols use TCP. This includes the familiar protocols HTTP, SMTP (mail) and FTP. Other protocols use UDP: DNS and SNMP to name a couple. TCP handles a lot of messy details which are necessary to ensure reliable data flow in spite of possible deficiencies in the network, such as lost or re-ordered packets. For example, TCP will automatically retransmit data that was not acknowledged by the peer within a reasonable time. TCP also paces data transmission so that it does not overflow the peers receive buffers (which are always finite) and does not overload intermediate nodes (routers) in the network. UDP leaves all of these details to the application, however UDP has some benefits that TCP cannot provide: one benefit is that UDP can broadcast to more than one peer, and another is that UDP preserves the concept of record boundaries which can be useful for some applications. TCP is a connection-oriented protocol. Two peers establish a TCP connection, which persists for the exclusive use of the two parties until it is mutually closed (in the usual case). UDP is connectionless. There is no special start-up or tear-down required for UDP communications. You can send a UDP packet at any time to any destination. Of course, the destination may not be ready to receive UDP packets, so the application has to handle this possibility. (In spite of being connectionless, we still sometimes refer to UDP connections or sessions with the understanding that the connection is a figment of your applications imagination.) This chapter describes how to implement your own application level protocols on top of TCP or UDP. The Dynamic C TCP/IP libraries can also be examined for further hints as to how to code your application. For example, HTTP.LIB contains the source for an HTTP web server.

Chapter 3: TCP and UDP Socket Interface

33

3.1 What is a Socket?


Both TCP and UDP make extensive use of the term socket. A TCP socket represents the connection state between the local host and the remote peer. When talking about TCP connections which traverse the Internet, a socket is globally unique because it is described by 4 numbers: the local and remote IP addresses (32 bits each), and the local and remote port numbers (16 bits each). Connections that do not traverse the Internet (e.g., between two hosts on an isolated LAN) are still unique within the attached network. UDP sockets do not have the global uniqueness property, since they are not connection-oriented. For UDP, a socket really refers to just the local side. For practical purposes, a socket is a structure in RAM that contains all the necessary state information. TCP sockets are considerably larger than UDP sockets since there is more connection state information to maintain. TCP sockets also require both a receive and a transmit buffer, whereas UDP sockets require only a receive buffer. With Dynamic C version 6.57, each socket must have an associated tcp_Socket structure of 145 bytes or a udp_Socket structure of 62 bytes. The I/O buffers are in extended memory. For Dynamic C 7.30 these sizes are 136 bytes and 44 bytes, respectively. For earlier versions of Dynamic C (than 6.57), each socket must have a tcp_Socket data structure that holds the socket state and I/O buffers. These structures are, by default, around 4200 bytes each. The majority of this space is used by the input and output buffers.

3.1.1 Port Numbers


Both TCP and UDP sockets make use of port numbers. Port numbers are a convenient method of allowing several simultaneous connections to exist between the same two hosts. Port numbers are also used to provide well-known starting points for common protocols. For example, TCP port number 23 is used for standard telnet connections. In general, port numbers below 1024 are used for standard services. Numbers between 1024 and 65535 are used for connections of a temporary nature. Often, the originator of a connection will select one of the temporary port numbers for its end of the connection, with the well-known number for the other end (which is often some sort of server). TCP and UDP port numbers are not related and operate in an independent space. However, the well-known port numbers for TCP and UDP services often match if the same sort of protocol can be made to run over TCP or UDP. When you open a socket using the TCP/IP libraries, you can specify a particular port number to use, or you can allow the library to pick a temporary port number for an ephemeral connection.

34

TCP/IP Users Manual

3.2 Allocating TCP and UDP Sockets


In all versions of Dynamic C, TCP and UDP socket structures must be allocated in static data storage. This is simply accomplished by declaring a static variable of type tcp_Socket or udp_Socket: static tcp_Socket my_sock; static udp_Socket my_udp_sock_array[20];

3.2.1 Allocating Socket Buffers


Starting with Dynamic C version 7.05, there are two macros that define the number of sockets available. These macros do not determine how many sockets you can allocate, but they do limit how many sockets you can successfully use. Each socket requires some resources which are not automatically available just because you declare a tcp_Socket structure. The additional resources are receive/transmit buffers (which are allocated in extended memory), and also socket semaphores if you are using C-OS/II. The relevant macros are:

MAX_TCP_SOCKET_BUFFERS
Determines the maximum number of TCP sockets with preallocated buffers. The default is 4. A buffer is tied to a socket with the first call to tcp_open() or tcp_listen(). If you use tcp_extopen() or tcp_extlisten() then these buffer resources are not used up, but only if you allocate your own buffers using xalloc().

MAX_UDP_SOCKET_BUFFERS
Determines the maximum number of UDP sockets with preallocated buffers. The default is 0. A buffer is tied to a socket with the first call to udp_open(). If you use udp_extopen() then these buffer resources are not used up, but only if you allocate your own buffers using xalloc(). Note that DNS does not need a UDP socket buffer since it manages its own buffer. Prior to version 7.30, DHCP and TFTP.LIB each need one UDP socket buffer. Starting with version 7.30, DHCP manages its own socket buffers. Prior to Dynamic C version 7.05, MAX_SOCKETS (deprecated) defined the number of sockets that could be allocated, not including the socket for DNS lookups. If you use libraries such as HTTP.LIB or FTP_SERVER.LIB, you must provide enough sockets in MAX_SOCKETS for them also. In Dynamic C 7.05 (and later), if MAX_SOCKETS is defined in an application program, MAX_TCP_SOCKET_BUFFERS will be assigned the value of MAX_SOCKETS. If you are using C-OS/II then there is a further macro which must be set to the correct value: MAX_SOCKET_LOCKS. This must count every socket (TCP plus UDP), including those used internally by the libraries. If you cannot calculate this exactly, then it is best to err on the side of caution by overestimating. The actual socket semaphore structure is not all that big (less than 70 bytes). The default value for MAX_SOCKET_LOCKS is the sum of MAX_TCP_SOCKET_BUFFERS and MAX_UDP_SOCKET_BUFFERS (plus 1 if DNS is being used).

Chapter 3: TCP and UDP Socket Interface

35

3.2.2 Socket Buffer Sizes


Starting with Dynamic C version 7.05, TCP and UDP I/O buffers are sized separately using:

TCP_BUF_SIZE
Determines the TCP buffer size. Defaults to 4096 bytes.

UDP_BUF_SIZE
Determines the UDP buffer size. Defaults to 4096 bytes. Compatibility is maintained with earlier versions of Dynamic C. If SOCK_BUF_SIZE is defined, TCP_BUF_SIZE and UDP_BUF_SIZE will be assigned the value of SOCK_BUF_SIZE. If SOCK_BUF_SIZE is not defined, but tcp_MaxBufSize is, then TCP_BUF_SIZE and UDP_BUF_SIZE will be assigned the value of tcp_MaxBufSize * 2. 3.2.2.1 User-Supplied Buffers Starting with Dynamic C version 7.05, a user can associate his own buffer with a TCP or UDP socket. The memory for the buffer must be allocated by the user. This can be done with xalloc(), which returns a pointer to the buffer. This buffer will be tied to a socket by a call to an extended open function: tcp_extlisten(), tcp_extopen() or udp_extopen(). Each function requires a long pointer to the buffer and its length be passed as parameters.

3.3 Opening TCP Sockets


There are two ways to open a TCP socket, passive and active. Passive open means that the socket is made available for connections originated from another host. This type of open is commonly used for Internet servers that listen on a well-known port, like 80 for HTTP (Hypertext Transfer Protocol) servers. Active open is used when the controller board is establishing a connection with another host which is (hopefully) listening on the specified port. This is typically used when the controller board is to be a client for some other server. The distinction between passive and active open is lost as soon as the connection is fully established. When the connection is established, both hosts operate on a peer-to-peer basis. The distinction between who is client and who is server is entirely up to the application. TCP itself does not make a distinction.

3.3.1 Passive Open


To passively open a socket, call tcp_listen()or tcp_extlisten(); then wait for someone to contact your device. You supply the listen function with a pointer to a tcp_Socket data structure, the local port number others will be contacting on your device, and possibly the IP address and port number that will be acceptable for the peer. If you want to be able to accept connections from any IP address or any port number, set one or both to zero. To handle multiple simultaneous connections, each new connection will require its own tcp_Socket and a separate call to one of the listen functions, but using the same local port number (lport value). The listen function will immediately return, and you must poll for the incoming connection. You can manually poll the socket using sock_established(). The proper procedure for fielding incoming connections is described below.
36 TCP/IP Users Manual

3.3.2 Active Open


When your Web browser retrieves a page, it actively opens one or more connections to the servers passively opened sockets. To actively open a connection, call tcp_open() or tcp_extopen(), which use parameters that are similar to the ones used in the listen functions. Supply exact parameters for remip and port, which are the IP address and port number you want to connect to; the lport parameter can be zero, causing an unused local port between 1024 and 65535 to be selected. If the open function returns zero, no connection was made. This could be due to routing difficulties, such as an inability to resolve the remote computers hardware address with ARP. Even if non-zero is returned, the connection will not be immediately established. You will need to check the socket status as described in the next section.

3.3.3 Waiting for Connection Establishment


When you open a TCP socket either passively or actively, you must wait for a complete TCP connection to be established. This is technically known as the 3-way handshake. As the name implies, at least 3 packets must be exchanged between the peers. Only after completion of this process, which takes at least one round-trip time, does the connection become fully established such that application data transfer can proceed. Unfortunately, the 3-way handshake may not always succeed: the network may get disconnected; the peer may cancel the connection; or the peer might even crash. The handshake may also complete, but the peer could immediately close or cancel the connection. These possibilities need to be correctly handled in a robust application. The consequences of not doing this right include lockedup sockets (i.e., inability to accept further connections) or protocol failures. The following code outlines the correct way to accept connections, and to recover in case of errors. if (!tcp_open(&my_socket, ...)) printf(Failed to open\n); else while(!sock_established(&my_socket)) { if (!tcp_tick(&my_socket)) { printf(Failed to establish\n); break; } } if (sock_established(&my_socket)) { printf(Established OK!\n); // do whatever needs to be done... } Notice the tcp_tick(&my_socket) call inside the while loop. This is necessary in order to test whether the handshake was aborted by the peer, or timed out. At the end of the loop, sock_established() tests whether the handshake did indeed complete. If so, then the socket is ready for data flow. Otherwise, the socket should be re-opened. The same basic procedure applies for passively opened sockets (i.e., tcp_listen()).

Chapter 3: TCP and UDP Socket Interface

37

3.3.4 Specifying a Listen Queue


A tcp_Socket structure can handle only a single connection at any one time. However, a passively opened socket may be required to handle many incoming connection requests without undue delay. To help smoothly process successive connection requests with a single listening socket, you can specify that certain TCP port numbers have an associated pending connection queue. If there is no queue, then incoming requests will be cancelled if the socket is in use. If there is a queue, then the new connections will be queued until the current active connection is terminated. To accept new connection requests when the passively opened socket is currently connected, use the function tcp_reserveport(). It takes one parameter, the port number where you want to accept connections. When a connection to that port number is requested, the 3-way handshaking is done even if there is not yet a socket available. When replying to the connection request, the window parameter in the TCP header is set to zero, meaning, I can take no bytes of data at this time. The other side of the connection will wait until the value in the window parameter indicates that data can be sent. Using the companion function, tcp_clearreserve(port number), causes TCP/IP to treat a connection request to the port in the conventional way. The macro USE_RESERVEDPORTS is defined by default. It allows the use of these two functions. When using tcp_reserveport, the 2MSL (Maximum Segment Lifetime) waiting period for closing a socket is avoided.

3.4 TCP Socket Functions


There are many functions that can be applied to an open TCP socket. They fall into three main categories: Control, Status, and I/O.

3.4.1 Control Functions for TCP Sockets


These functions change the status of the socket or its I/O buffer.

sock_abort sock_close sock_flush sock_flushnext

tcp_extlisten tcp_extopen tcp_listen tcp_open

The open and listen functions have been explained in previous sections. Call sock_close() to end a connection. This call may not immediately close the connection because it may take some time to send the request to end the connection and receive the acknowledgements. If you want to be sure that the connection is completely closed before continuing, call tcp_tick() with the socket structures address. When tcp_tick() returns zero, then the socket is completely closed. Please note that if there is data left to be read on the socket, the socket will not completely close. Call sock_abort() to cancel an open connection. This function will cause a TCP reset to be sent to the other end, and all future packets received on this connection will be ignored. For performance reasons, data may not be immediately sent from a socket to its destination. If your application requires the data to be sent immediately, you can call sock_flush(). This
38 TCP/IP Users Manual

function will try sending any pending data immediately. If you know ahead of time that data needs to be sent immediately, call sock_flushnext() on the socket. This function will cause the next set of data written to the socket to be sent immediately, and is more efficient than sock_flush().

3.4.2 Status Functions for TCP Sockets


These functions return useful information about the status of either a socket or its I/O buffers.

sock_alive sock_bytesready sock_dataready sock_established sock_iface sock_rbleft

sock_rbsize sock_rbused sock_tbleft sock_tbsize sock_tbused tcp_tick

tcp_tick() is the daemon that drives the TCP/IP stack, but it also returns status information. When you supply tcp_tick() with a pointer to a tcp_Socket (a structure that identifies a particular socket), it will first process packets and then check the indicated socket for an established connection. tcp_tick() returns zero when the socket is completely closed. You can use this return value after calling sock_close() to determine if the socket is completely closed. sock_close(&my_socket); while(tcp_tick(&my_socket)) { // you can do other things here while waiting for the socket to be completely closed } The status functions can be used to avoid blocking when using sock_write() and some of the other I/O functions. As illustrated in the following code, you can make sure that there is enough room in the buffer before adding data with a blocking function. if(sock_tbleft(&my_socket,size)) { sock_write(&my_socket,buffer,size); } The following block of code ensures that there is a string terminated with a new line in the buffer, or that the buffer is full before calling sock_gets(): sock_mode(&my_socket,TCP_MODE_ASCII); if(sock_bytesready(&my_socket) != -1) { sock_gets(buffer,MAX_BUFFER); }

Chapter 3: TCP and UDP Socket Interface

39

3.4.3 I/O Functions for TCP Sockets


These functions handle all I/O for a TCP socket.

sock_aread sock_awrite sock_axread sock_axwrite sock_fastread sock_fastwrite sock_getc sock_gets

sock_preread sock_putc sock_puts sock_read sock_write sock_xfastread sock_xfastwrite

There are two modes of reading and writing to TCP sockets: ASCII and binary. By default, a socket is opened in binary mode, but you can change the mode with a call to sock_mode(). When a socket is in ASCII mode, it is assumed that the data is an ASCII stream with record boundaries on the newline characters for some of the functions. This behavior means sock_bytesready() will return 0 only when a complete newline-terminated string is in the buffer or the buffer is full. The sock_puts() function will automatically place a newline character at the end of a string, and the sock_gets() function will strip the newline character. Do not use sock_gets()in binary mode.

40

TCP/IP Users Manual

3.5 UDP Socket Overview


The UDP protocol is useful when sending messages where either a lost message does not cause a system failure or is handled by the application. Since UDP is a simple protocol and you have control over the retransmissions, you can decide if you can trade low latency for high reliability. Broadcast Packets UDP can send broadcast packets (i.e., to send a packet to a number of computers on the same network). This is accomplished by setting the remote IP address to -1, in either a call to udp_open() or a call to udp_sendto(). When used properly, broadcasts can reduce overall network traffic because information does not have to be duplicated when there are multiple destinations. Checksums There is an optional checksum field inside the UDP header. This field verifies the header and the data. This feature can be disabled on a reliable network where the application has the ability to detect transmission errors. Disabling the UDP checksum can increase the performance of UDP packets moving through the TCP/IP stack. This feature can be modified by: sock_mode(s, UDP_MODE_CHK); sock_mode(s, UDP_MODE_NOCHK); // enable checksums // disable checksums

The first parameter is a pointer to the sockets data structure, either tcp_Socket or udp_Socket. In Dynamic C version 7.20, some convenient macros offer a safer, faster alternative to using sock_mode(). They are udp_set_chk(s) and udp_set_nochk(s). Improved Interface With Dynamic C version 7.05 there is a redesigned UDP API. The new interface is incompatible with the previous one. Section 3.6 covers the new interface and Section 3.7 covers the previous one. See Section 3.7.5 for information on porting an older program to the new UDP interface.

Chapter 3: TCP and UDP Socket Interface

41

3.6 UDP Socket Functions (7.05 and later)


Starting with Dynamic C 7.05, the UDP implementation is a true record service. It receives distinct datagrams and passes them as such to the user program. The socket I/O functions available for TCP sockets will no longer work for UDP sockets.

3.6.1 Control Functions for UDP Sockets


These functions change the status of the socket or its I/O buffer.

udp_close udp_extopen udp_open 3.6.2 Status Function for UDP Sockets


These functions return useful information about the status of either a socket or its I/O buffers.

sock_bytesready sock_dataready sock_rbleft sock_rbsize sock_rbused udp_peek

For a UDP socket, sock_bytesready() returns the number of bytes in the next datagram in the socket buffer, or -1 if no datagrams are waiting. Note that a return of 0 is valid, since a datagram can have 0 bytes of data.

3.6.3 I/O Functions for UDP Sockets


These functions handle datagram-at-a-time I/O:

udp_recv udp_recvfrom udp_send udp_sendto

The write function, udp_sendto(), allows the remote IP address and port number to be specified. The read function, udp_recvfrom(), identifies the IP address and port number of the host that sent the datagram. There is no longer a UDP read function that blocks until data is ready.

42

TCP/IP Users Manual

3.7 UDP Socket Functions (pre 7.05)


This interface is basically the TCP socket interface with some additional functions for simulating a record service. Some of the TCP socket functions work differently for UDP because of its connectionless state. The descriptions for the applicable functions detail these differences.

3.7.1 I/O Functions for UDP Sockets


Prior to Dynamic C 7.05, the functions that handle UDP socket I/O are mostly the same functions that handle TCP socket I/O.

sock_fastread sock_fastwrite sock_getc sock_gets sock_preread sock_putc sock_puts

sock_read sock_recv sock_recv_from sock_recv_init sock_write udp_close udp_open

Notice that there are three additional I/O functions that are only available for use with UDP sockets: sock_recv(), sock_recv_from() and sock_recv_init(). The status and control functions that are available for TCP sockets also work for UDP sockets, with the exception of the open functions, tcp_listen() and tcp_open().

3.7.2 Opening and Closing a UDP Socket


udp_open() takes a remote IP address and a remote port number. If they are set to a specific value, all incoming and outgoing packets are filtered on that value (i.e., you talk only to the one remote address). If the remote IP address is set to -1, the UDP socket receives packets from any valid remote address, and outgoing packets are broadcast. If the remote IP address is set to 0, no outgoing packets may be sent until a packet has been received. This first packet completes the socket, filling in the remote IP address and port number with the return address of the incoming packet. Multiple sockets can be opened on the same local port, with the remote address set to 0, to accept multiple incoming connections from separate remote hosts. When you are done communicating on a socket that was started with a 0 IP address, you can close it with sock_close() and reopen to make it ready for another source.

3.7.3 Writing to a UDP Socket


Prior to Dynamic C 7.05, the normal socket functions used for writing to a TCP socket will work for a UDP socket, but since UDP is a significantly different service, the result could be different. Each atomic writesock_putc(), sock_puts(), sock_write(), or sock_fastwrite()places its data into a single UDP packet. Since UDP does not guarantee delivery or ordering of packets, the data received may be different either in order or content than the data sent. Packets may also be duplicated if they cross any gateways. A duplicate packet may be received well after the original.
Chapter 3: TCP and UDP Socket Interface 43

3.7.4 Reading From a UDP Socket


There are two ways to read UDP packets prior to Dynamic C 7.05. The first method uses the same read functions that are used for TCP: sock_getc(), sock_gets(), sock_read(), and sock_fastread(). These functions will read the data as it came into the socket, which is not necessarily the data that was written to the socket. The second mode of operation for reading uses the sock_recv_init(), sock_recv(), and sock_recv_from() functions. The sock_recv_init() function installs a large buffer area that gets divided into smaller buffers. Whenever a datagram arrives, it is stuffed into one of these new buffers. The sock_recv() and sock_recv_from() functions scan these buffers. After calling sock_recv_init on the socket, you should not use sock_getc(), sock_read(), or sock_fastread(). The sock_recv() function scans the buffers for any datagrams received by that socket. If there is a datagram, the length is returned and the user buffer is filled, otherwise sock_recv() returns zero. The sock_recv_from() function works like sock_recv(), but it allows you to record the IP address where the datagram originated. If you want to reply, you can open a new UDP socket with the IP address modified by sock_recv_from().

3.7.5 Porting Programs from the older UDP API to the new UDP API
To update applications written with the older-style UDP API, use the mapping information in the following table.

UDP API prior to Dynamic C 7.05

UDP API starting with Dynamic C 7.05

MAX_SOCKETS SOCK_BUF_SIZE udp_open() sock_write(), sock_fastwrite() sock_read()(blocking function) sock_fastread() sock_recv_init() sock_recv() sock_recv_from() sock_close() sock_bytesready() sock_dataready()

MAX_UDP_SOCKET_BUFFERS and MAX_TCP_SOCKET_BUFFERS UDP_BUF_SIZE and TCP_BUF_SIZE udp_open() udp_send() or udp_sendto() udp_recv() or udp_recvfrom() (nonblocking functions) udp_recv() or udp_recvfrom() udp_extopen() (to specify your own buffer) udp_recv() udp_recvfrom() sock_close() or udp_close() sock_bytesready() sock_dataready()

44

TCP/IP Users Manual

3.8 Skeleton Program


The following program is a general outline for a Dynamic C TCP/IP program. The first couple of defines set up the default IP configuration information. The memmap line causes the program to compile as much code as it can in the extended code window. The use line causes the compiler to compile in the Dynamic C TCP/IP code using the configuration data provided above it.

Program Name: Samples\tcpip\icmp\pingme.c


/* * Starting with Dynamic C 7.30, the network addresses are initialized by defining the * following macro to identify the desired configuration in the file tcp_config.lib. */ #define TCPCONFIG 1 // static configuration of single Ethernet interface. /* * Prior to Dynamic C 7.30, you must change the following values to whatever * your local IP address, netmask, and gateway are. Contact your network * administrator for these numbers. */ // #define MY_IP_ADDRESS "10.10.6.101" // #define MY_NETMASK "255.255.255.0" // #define MY_GATEWAY "10.10.6.19" #memmap xmem #use dcrtcp.lib main() { sock_init(); for (;;) { tcp_tick(NULL); } } To run this program, start Dynamic C and open the Samples\TCPIP\ICMP\PINGME.C file. If you are using a Dynamic C version prior to 7.30, edit the MY_IP_ADDRESS, MY_NETMASK, and MY_GATEWAY macros to reflect the appropriate values for your device. Otherwise, edit your tcpconfig.lib (or custom_config.lib) file with appropriate network addresses for your device and define TCPCONFIG to access the desired configuration information. Run the program and try to run ping 10.10.6.101 from a command line on a computer on the same physical network, replacing 10.10.6.101 with your value for MY_IP_ADDRESS.

Chapter 3: TCP and UDP Socket Interface

45

3.8.1 TCP/IP Stack Initialization


The main() function first initializes the TCP/IP stack with a call to sock_init(). This call initializes internal data structures and enables the Ethernet chip, which will take a couple of seconds with the RealTek chip. At this point, the TCP/IP stack is ready to handle incoming packets.

3.8.2 Packet Processing


Incoming packets are processed whenever tcp_tick() is called. The user-callable functions that call tcp_tick() are: tcp_open, udp_open, sock_read, sock_write, sock_close, and sock_abort. Some of the higher-level protocols, e.g., HTTP.LIB will call tcp_tick() automatically. Call tcp_tick()periodically in your program to ensure that the TCP/IP stack has had a chance to process packets. A rule of thumb is to call tcp_tick() around 10 times per second, although slower or faster call rates should also work. The Ethernet interface chip has a large buffer memory, and TCP/IP is adaptive to the data rates that both ends of the connection can handle; thus the system will generally keep working over a wide variety of tick rates.

3.9 TCP/IP Daemon: tcp_tick()


tcp_tick() is a fundamental function for the TCP/IP library. It has two uses: it drives the background processing necessary to maintain up-to-date information; and it may also be used to test TCP socket state. The latter use is described in the next section. Note that tcp_tick() does more than just TCP processing: it is also necessary for UDP and other internal protocols such as ARP and ICMP. It also (as of Dynamic C 7.30) controls interface status. The computing time consumed by each call to tcp_tick() varies. Rough numbers are less than a millisecond if there is nothing to do, tens of milliseconds for typical packet processing, and hundreds of milliseconds under exceptional circumstances. In general, the more active sockets that are in use simultaneously, the longer it will take for tcp_tick() to complete, however there is not much increase for reasonable numbers of sockets. It is recommended that you call tcp_tick() at the head of the main application processing loop. If you have any other busy-wait loops in your application, you should arrange for tcp_tick() to be called in each such loop. TCP/IP library functions that are documented as blocking will always include calls to tcp_tick(), so you do not have to worry about it. Library functions which are documented as non-blocking (e.g., sock_fastread()) do not in general call tcp_tick(), so your application will need to do it. Some of the provided application protocols (such as HTTP and FTP) have their own tick functions (e.g., http_handler() and ftp_tick()). When you call such a function, there is no need to call tcp_tick() since the other tick function will always do this for you.

46

TCP/IP Users Manual

3.9.1 tcp_tick() for Robust Applications


It goes without saying that your application should be designed to be robust. You should be aware that an open TCP socket may become disconnected at any time. The disconnection can arise because of a time-out (caused by network problems), or because the peer application sent a RST (reset) flag to abort the connection, the interface went down, or even because another part of your application called sock_abort(). Your application should check for this condition, preferably in the main socket processing loop, by calling tcp_tick() with the socket address. Since tcp_tick() needs to be called regularly, this does not add much overhead if you have a single socket. For applications which manage multiple sockets, you can use the sock_alive() function (new for Dynamic C 7.30). If tcp_tick() or sock_alive() returns zero for a socket, then the socket may be re-opened after your application recovers. Regular checking of socket status is also convenient in that it can simplify the rest of your application. In effect, checking socket status in your main application loop concentrates socket error handling at a single point in the code. There is less need to perform error handling after other calls to TCP/IP functions. For example, the sock_fastread() function normally returns a non-negative value, but it can return -1 if there is a problem with the socket. An application function which calls sock_fastread() needs to check for this code, however it can choose to merely return to the caller (the main loop) if this code is detected, rather than handling the error at the point where it was first detected. This works because if sock_fastread() returns -1, tcp_tick() will return zero for that socket.

3.9.2 Global Timer Variables


The TCP/IP stack depends on the values for MS_TIMER, and SEC_TIMER. Problems may be encountered if the application program changes these values during execution.

3.10 State-Based Program Design


An efficient design strategy is to create a state machine within a function and pass the sockets data structure as a function parameter. This method allows you to handle multiple sockets without the services of a multitasking kernel. This is the way the HTTP.LIB functions are organized. Many of the common Internet protocols fit well into this state machine model. The general states are:

Waiting to be initialized. Waiting for a connection. Connected states that perform the real work. Waiting for the socket to be closed.

An example of state-based programming is SAMPLES\TCPIP\STATE.C. This program is a basic Web server that should work with most browsers. It allows a single connection at a time, but can be extended to allow multiple connections.

Chapter 3: TCP and UDP Socket Interface

47

In general, when defining the set of states for a socket connection, you will need to define a state for each point where the application needs to wait for some external event. At a minimum, this will include states when waiting for

session establishment new received data space in the transmit buffer for write data session termination

For non-trivial application protocols, the states in-between session establishment and session termination may need to be embellished into a set of sub-states which reflect the stage of processing of input or output. Sometimes, input and output states may need to overlap. If they do not, then you typically have a step-by-step protocol. Otherwise, you have an application that uses receive and transmit independently. Step-by-step protocols are easier to implement, since there is no need to be able to overlap two (or more) sets of state. For read states, which are waiting for some data to come in from the peer, you will typically call one of the non-blocking socket read functions to see if there is any data available. If you are expecting a fixed length of data (e.g., a C structure encoded in the TCP data stream), then it is most convenient to use the sock_aread() function which was introduced in Dynamic C 7.30. Otherwise, if you cannot tell how much data will be required to go to the next state, then you will have to call sock_preread() to check the current data, without prematurely extracting it from the socket receive buffer. For write states, you can just keep calling sock_fastwrite() until all the data for this state is written. If you have a fixed amount of data, sock_awrite() is more convenient since you do not have to keep track of partially written data.

3.10.1 Blocking vs. Non-Blocking


There is a choice between blocking and non-blocking functions when doing socket I/O. 3.10.1.1 Non-Blocking Functions The sock_fastread() and sock_preread() functions read all available data in the buffers, and return immediately. Similarly, the sock_fastwrite() function fills the buffers and returns the number of characters that were written. When using these functions, you must ensure that all of the data were written completely. offset=0; while(offset<len) { bytes_written = sock_fastwrite(&s, buf+offset, len-offset); if(bytes_written < 0) { // error handling } offset += bytes_written; }

48

TCP/IP Users Manual

3.10.1.2 Blocking Functions The other functions (sock_getc(), sock_gets(), sock_putc(), sock_puts(), sock_read() and sock_write()) do not return until they have completed or there is an error. If it is important to avoid blocking, you can check the conditions of an operation to ensure that it will not block. sock_mode(socket,TCP_MODE_ASCII); // ... if (sock_bytesready(&my_socket) != -1){ sock_gets(buffer, MAX_BUFFER); } In this case sock_gets() will not block because it will be called only when there is a complete new line terminated record to read.

3.11 TCP and UDP Data Handlers


Starting with Dynamic C 7.301, your application can specify data handler callback functions for TCP and UDP sockets. The data handler callback may be specified as a parameter to the tcp_open(), tcp_extopen(), tcp_listen(), tcp_extlisten(), udp_open(), udp_extopen() and udp_waitopen() functions. The UDP data handler callback is always available. The TCP handler is only available if you #define TCP_DATAHANDLER before including dcrtcp.lib. Both types of callback use the same function prototype, however, the parameters are interpreted slightly differently. The prototype for a suitable callback function is: int my_data_handler( int event, void * socket, ll_Gather * g, void * info ); event indicates the type of callback. It is one of a predefined set of constants specified in the table below. socket is a pointer to the socket structure (TCP or UDP). g contains a number of fields which may be accessed to find additional information, including the data stream or packet. info points to a structure which depends on the type of socket: _udp_datagram_info if the socket is UDP, or NULL for TCP sockets.

1. Data handler pointers were provided to the tcp_open etc. functions prior to this release, however the interface was not documented, and does not work in the way described herein. Chapter 3: TCP and UDP Socket Interface 49

The ll_Gather structure is defined and documented in NET.LIB. It is printed here for reference: typedef struct { byte iface; byte spare; word len1; void * data1; word len2; long data2; word len3; long data3; } ll_Gather; // Destination interface // // // // // // Length of root data section Root data (e.g., link, IP, transport headers) Length of first xmem section First xmem data extent (physical address) Length of second xmem section Second xmem data extent (physical address)

The _udp_datagram_info is defined in UDP.LIB. It is documented with the udp_peek() function. For UDP sockets, the callback is invoked for each packet received by the socket. For TCP sockets, the callback is invoked whenever new data is available that could otherwise be returned by sock_fastread(). The advantages of using the data handler callback are

Less application overhead calling sock_dataready() or sock_fastread(). Data copy to root buffers can be avoided. Ability to transform data in the socket buffer (e.g., decryption). For UDP, may avoid the need to copy incoming data into the socket receive buffer. Minimizes latency between tcp_tick() receive processing, and application processing. Allows event-driven programming style.

The following table lists the parameters to the callback for each event type.
Table 2. Parameters for each type of callback event s g info notes

UDP_DH_INDATA UDP_DH_ICMPMSG TCP_DH_LISTEN TCP_DH_OPEN TCP_DH_ESTAB TCP_DH_INDATA TCP_DH_OUTBUF

udp_Socket udp_Socket tcp_Socket tcp_Socket tcp_Socket tcp_Socket tcp_Socket

pkt data pkt data NULL NULL NULL seg data NULL

UDI UDI NULL NULL NULL NULL NULL

Normal received data ICMP message received for this socket Passive open call (e.g., tcp_extlisten()) Active open call (e.g., tcp_extopen()) 3-way handshake complete, ready for data transfer Incoming stream data New space in transmit buffer (data acknowledged by peer)

50

TCP/IP Users Manual

Table 2. Parameters for each type of callback event s g info notes

TCP_DH_INCLOSE

tcp_Socket

NULL NULL NULL NULL NULL pkt data ?

NULL NULL NULL NULL NULL NULL ?

No further incoming data (peer sent FIN) No further outgoing data (application closed socket, sent FIN) Socket completely closed Application called sock_abort Peer sent RST flag ICMP message associated with this socket Reserved for future use. Callback should always return zero.

TCP_DH_OUTCLOSE tcp_Socket TCP_DH_CLOSED TCP_DH_ABORT TCP_DH_RESET TCP_DH_ICMPMSG other tcp_Socket tcp_Socket tcp_Socket tcp_Socket ?

3.11.1 UDP Data Handler


For UDP sockets, the callback is invoked as soon as a new datagram is demultiplexed to the socket. For event type UDP_DH_INDATA,the ll_Gather struct is set up with the interface number and pointers to the data in the receive buffers (not the UDP socket receive buffer, since the data has not yet been copied there). The info structure is a pointer to _udp_datagram_info (UDI), which is set up with the usual udp_peek information such as the host IP address and port number, and whether the datagram is in fact an ICMP error message. If an ICMP message is received, the event type is set to UDP_DH_ICMPMSG. The callback should return 0 to continue with normal processing (i.e., add the datagram to the socket buffer), or 1 to indicate that the datagram has been processed and should not be added to the socket buffer The data pointers in the ll_Gather structure are the physical address (and length) of one or two datagram fragments in the main network receive buffers. (Currently, only one address will be provided, since datagrams are reassembled before passing to the UDP handler). There is also a root data pointer in the ll_Gather structure, that is set to point to the IP and UDP headers of the datagram.

3.11.2 TCP Data Handler


The TCP data handler is only available if you #define TCP_DATAHANDLER. It is invoked with a large number of different event types. Most of the events are for significant changes in the TCP socket state. You can use these events to perform customized handling of socket open and close. Apart from TCP_DH_INDATA and TCP_DH_ICMPMSG, the ll_Gather structure is not passed (g is set to NULL). Currently, the info parameter is always null for TCP sockets. If your callback function does not understand a particular event type, or is not interested, it should return zero. This will allow for upward compatibility if new callback events are introduced. For convenience in coding the callback, you can use the user_data field in the tcp_Socket structure to hold some application-specific data which is to be associated with a socket instance. There is no

Chapter 3: TCP and UDP Socket Interface

51

API for accessing this field; just use s->user_data. This field is only available if you have defined TCP_DATAHANDLER, and only for TCP sockets (not UDP). There is no guarantee on the order in which events will arrive for a socket. The exceptions are that TCP_DH_LISTEN or TCP_DH_OPEN will always be first, and TCP_DH_CLOSED will always be last. There is no guarantee that the callback will be invoked with TCP_DH_INCLOSE or TCP_DH_OUTCLOSE before TCP_DH_CLOSED. TCP_DH_OUTBUF indicates that some previously transmitted data has been acknowleged by the peer. Generally, this means that there is more space available in the transmit buffer. The callback can write data to the socket using sock_fastwrite() and other non-blocking write functions. The available transmit buffer space may be determined by sock_tbleft() function. When TCP_DH_ESTAB is invoked, the transmit buffer is normally completely empty, so the callback can write a reasonable amount of data to start with. The TCP_DH_INDATA event callback is invoked after the incoming data has been stored in the socket buffer. It is only invoked if there is new data available from the peer. The ll_Gather structure is set up with one or two physical address pointers to the new data, and the logical pointer points to the IP header of the most recent datagram which provided the new data. Usually there will be only one physical address, however there may be two if the socket buffer happens to wrap around at that point. The callback will need to be coded to handle this possibility if it is accessing the data directly out of the xmem buffer. The TCP_DH_INDATA callback is allowed to modify the new data in-place, if desired. This may be used to provide transparent decryption or similar services. There are some restrictions which apply to callback code. Primarily, it is not allowed to invoke tcp_tick() directly or indirectly, since that will cause recursion into tcp_tick(). It will be possible to call sock_fastwrite() or udp_sendto() e.g., to generate some sort of response. Since sock_fastwrite() needs to buffer data, there is a possibility that there may be insufficient room in the transmit buffer for the generated response. Thus the callback will need to be carefully coded to avoid getting into a buffer deadlock situation if it generates responses. It will also need to co-ordinate with the rest of the application, since the application will otherwise have to contend with the possibility of arbitrary data being inserted in the write stream by the callback.
NOTE: The application must call sock_fastread() or other read functions to

actually remove data from the TCP socket receive buffer unless the data handler callback is coded to call sock_fastread() itself. If neither the data handler nor the rest of the application actually read the received data, then the TCP connection will become blocked in the read direction.

52

TCP/IP Users Manual

3.12 Multitasking and TCP/IP


Dynamic Cs TCP/IP implementation is compatible with both C/OS-II and with the language constructs that implement cooperative multitasking: costatements and cofunctions. Note that TCP/IP is not compatible with the slice statement.

3.12.1 C/OS-II
The TCP/IP stack may be used with the C/OS-II real-time kernel. The line #use ucos2.lib must appear before the line #use dcrtcp.lib in the application program. Also be sure to call OSInit() before calling sock_init(). Dynamic C version 7.05 and later requires the macro MAX_SOCKET_LOCKS for C/OS-II support. If it is not defined, it will default to MAX_TCP_SOCKET_BUFFERS + TOTAL_UDP_SOCKET_BUFFERS (which is MAX_UDP_SOCKET_BUFFERS + 1 if there are DNS lookups). Buffers xallocd for socket I/O should be accounted for in MAX_SOCKET_LOCKS.

3.12.2 Cooperative Multitasking


The following program demonstrates the use of multiple TCP sockets with costatements.

Chapter 3: TCP and UDP Socket Interface

53

Program Name: costate_tcp.c


// #define MY_IP_ADDRESS "10.10.6.11" // #define MY_NETMASK "255.255.255.0" // #define MY_GATEWAY "10.10.6.1" #define TCPCONFIG 1 #define PORT1 8888 #define PORT2 8889 #define SOCK_BUF_SIZE 2048 #define MAX_SOCKETS 2 #memmap xmem #use "dcrtcp.lib" tcp_Socket Socket_1; tcp_Socket Socket_2; #define MAX_BUFSIZE 512 char buf1[MAX_BUFSIZE], buf2[MAX_BUFSIZE]; // The function that actually does the TCP work cofunc int basic_tcp[2](tcp_Socket *s, int port, char *buf){ auto int length, space_avaliable; tcp_listen(s, port, 0, 0, NULL, 0); // wait for a connection while((-1 == sock_bytesready(s)) && (0 == sock_established(s))) // give other tasks time to do things while we are waiting yield; while(sock_established(s)) { space_avaliable = sock_tbleft(s); // limit transfer size to MAX_BUFSIZE, leave room for '\0' if(space_avaliable > (MAX_BUFSIZE-1)) space_avaliable = (MAX_BUFSIZE-1); // get some data length = sock_fastread(s, buf, space_avaliable); if(length > 0) { // did we receive any data? buf[length] = '\0'; // print it to the Stdio window printf("%s",buf); // send it back out to the user's telnet session // sock_fastwrite will work-we verified the space beforehand sock_fastwrite(s, buf, length); } yield; } sock_close(s); return 1; } // give other tasks time to run

54

TCP/IP Users Manual

Program Name: costate_tcp.c (continued)


main() { sock_init(); while (1) { costate { // Go do the TCP/IP part, on the first socket wfd basic_tcp[0](&Socket_1, PORT1, buf1); } costate { // Go do the TCP/IP part, on the second socket wfd basic_tcp[1](&Socket_2, PORT2, buf2); } costate { // drive the tcp stack tcp_tick(NULL); } costate { // Can insert application code here! waitfor(DelayMs(100)); } } }

Chapter 3: TCP and UDP Socket Interface

55

56

TCP/IP Users Manual

4. Optimizing TCP/IP Performance


Once you have a TCP/IP application coded and working, it is worthwhile to tune the application to get the best possible performance. There is usually a trade-off between performance and memory usage. If more memory is available, you can specify larger data buffers to improve overall performance. Conversely, if performance is already adequate, you can reduce buffer sizes to make room for more application functionality. Some performance improvements can be made without large increases in memory usage. To make these improvements, you will need to understand how TCP, IP and the properties of the network work and interact. This is a complex subject, which is well covered in various texts. This section concentrates on the characteristics of the Dynamic C TCP/IP stack. Most of the discussion is centered around Dynamic C version 7.30, but many of the principles apply to earlier releases. The discussion also concentrates on TCP. UDP is also mentioned where appropriate, however UDP performance is mainly determined by the application so there are not as many tuning controls available in the Dynamic C libraries for tuning UDP performance. The type of application has a large bearing on the performance tuning options which will be most appropriate. Here are some basic types of application which have different performance requirements:

bulk loader: an application which periodically uploads large amounts of data (such as a
log) to a server

casual server: one which just needs to process occasional commands which come in from
the network. This includes interactive servers such as telnet.

master controller: one which sends short data bursts to a number of slave controllers,
which must be sent and processed in a timely manner

web server: a web-enabled appliance protocol translator: accepts stream of data, perhaps serial, and converts to a TCP data
stream, or vice-versa All these application types have different requirements for the basic properties of a communications channel, namely bandwidth, throughput and latency. The bandwidth of a channel is the maximum sustained rate of end-to-end data transmission, in bytes per second. A full-duplex channel has the same bandwidth in each direction, independent of data traffic flowing in the opposite direction. In a half-duplex channel, the total bandwidth is divided between both directions. Ethernet is usually half-duplex in that an Ethernet chip cannot send and receive at the same time, however some types of Ethernet can run full-duplex. The throughput of a channel is related to bandwidth, but is used to express the amount of useful data that can be transmitted through the channel in a fixed (specified) amount of time, using a practical transport protocol (i.e., a protocol which adds some overhead to each message). Throughput generally improves as the bandwidth rises, and as the time interval increases. Throughput is always less than bandwidth for finite time intervals or practical protocols, since there is usually some overhead to establish the connection in the first place, as well as overhead during the transmission itself.
Chapter 4: Optimizing TCP/IP Performance 57

The latency of a channel can have several definitions. For our purposes, it is the minimum possible time delay between sending of a message, its receipt by the other end, and the reception of a reply; in other words, the round-trip-time (RTT). On electrical and radio channels, the latency is related to the physical length of the link and the speed of light. On channels which are more complex than a simple electrical connection, there may also be intermediate nodes which buffer the data being transmitted: this can add delays which are much larger than the speed of light between the end nodes. Note that round-trip times are important for most communications protocols: not only do we want to send data, but we also want to receive an acknowledgment that the other end received the data. Some examples of real networks may be helpful here. Note that the values given for RTT are approximations since they depend on the length of the connection, the sizes of packets sent, or intermediate nodes. Throughput is specified for an infinite time interval, assuming TCP over IP with 600 bytes of data per packet, and no data in the acknowledgment The RTT figure assumes the same size packets.
Table 3. Channel characteristics for selected networks Type Bandwidth (Byte/sec) RTT (msec) Throughput (Byte/sec)

Local 10Base-T Ethernet PPP over 8N1 serial (57.6k) PPPoE over 1.5Mbit DSL

1.25M 5760 187k

0.6 120 4

1M 5000 150k

The above table does not count any delay in the host which generates the response, nor any delay passing through the Internet. These represent minimum possible RTTs.

4.1 DBP and Sizing of TCP Buffers


An important quantity derived from the above is known as Delay-Bandwidth Product (DBP). As the name suggests, this is the product of bandwidth and RTT, and has units of bytes. It represents the maximum amount of data (and overhead) that can exist in the network at any point in time. This number has implications for sizing of TCP socket buffers. The DBP for local 10Base-T Ethernet is about 750 bytes. For local Ethernet connections, the DBP is about the same as the packet size of the transmitted data. For wider area networks that have significant propagation delays, the DBP can increase substantially. For example, satellite links can add several 100s of milliseconds to the RTT. If the bandwidth is high enough, the DBP can exceed the packet size by orders of magnitude. This means that several packets may be in transit at the same time. The DBP is important for TCP connections. This is because TCP is able to transmit a large number of packets into the network without having to wait for an acknowledgement for each one. Similarly, a TCP can receive a large number of packets without necessarily acknowledging them all. In fact, TCP only has to acknowledge the most recent packet; the sender can assume that all earlier packets are implicitly acknowledged.

58

TCP/IP Users Manual

How does all this apply to sizing of TCP socket buffers? It basically means that there is little point in making the buffers (both transmit and receive) larger than the expected maximum DBP of the communications channel. For connections which are expected to traverse the Internet, you may need quite large buffers. For local Ethernet only, the buffers need not be larger than, say, two packets. The maximum packet size is a compromise between performance and memory usage. The largest packet supported by dcrtcp.lib is 1500 bytes, which is dictated by the limits of Ethernet. Dynamic Cs default packet size is 600 bytes. Using large packet sizes improves performance for bulk data transfer, but has little effect for interactive traffic. Performance is improved for large packet sizes mainly because there is less CPU overhead per byte. There is a roughly fixed amount of CPU time required to process each packet. This is obviously better utilized if there are a large number of bytes per packet. When using Ethernet, the Rabbit processor is limited in its overall TCP/IP throughput by CPU power. 10Base-T Ethernet is capable of 1MB/sec for TCP sockets1, however the Rabbit 2000 running at 21MHz will only be able to transmit at about 270kB/sec when sending 1500 byte packets. Receive rate is slightly slower at about 220kB/sec. This scales approximately linearly with respect to CPU clock speed as well as application use of the CPU. In short, current Rabbit-based boards cannot use the full bandwidth of a local Ethernet link. The situation changes for PPP over serial. In this case, the serial port bandwidth is less than the rate at which packets can be generated or received. Also, PPP is typically used to access peers over the Internet, so there may be a much larger DBP than for a pure point-to-point link. For PPP serial links, smaller packet sizes, e.g. 256 bytes, are satisfactory for bulk data transfers without impacting interactive traffic, should that be required. Socket buffer sizes should be determined based on the expected Internet RTTs, which may be 1 second or more. For a 57.6kbps serial link, the DBP is 5000 bytes for 1 second RTT, thus the socket buffers should be about this size for receive and transmit. TCP is adaptive to changing network conditions. For example, the RTT can vary considerably at different times of day, and communication channels can become congested. TCP is designed to cope with these conditions without exacerbating any existing problems, however socket buffer and packet sizes are usually constants for the application so they need to be selected with due consideration to the most common conditions.

1. Assuming there is no other traffic on the Ethernet, and that collisions are rare. This is rarely the case, so a 50-80% utilization of bandwidth is considered the maximum desirable Ethernet load. Chapter 4: Optimizing TCP/IP Performance 59

4.2 TCP Performance Tuning


TCP is a well-designed protocol, and provides nearly optimum performance over a wide range of conditions. Obtaining the best possible performance requires the application to co-operate with TCP by setting the correct options if the defaults are not optimal, making the most efficient use of the socket API functions, and providing appropriate memory and CPU resources. The available performance-related options are:

whether to use the Nagle algorithm settings for time-out values whether to define a pending connection queue (reserved port) setting the IP Type Of Service field packet, buffer and MTU sizes ARP cache size (for Ethernet).

Sizing of buffers was discussed in the previous section. The following sections discuss the other performance controls.

4.2.1 The Nagle Algorithm


The Nagle algorithm is an option for TCP sockets. It modifies the transmit processing for a socket, but has no effect on receive processing. The TCP/IP library allows Nagle to be applied on a persocket basis. Most applications should leave the Nagle algorithm enabled for each TCP socket, which is the default. This provides the best utilization of bandwidth, since it prevents many small packets from being sent where one big packet would be preferable. The main reason to override the default, and disable the Nagle algorithm, is for applications that require the least possible delay between writing data to the socket, and its receipt by the peer application. This comes at the expense of efficiency, so you should carefully consider whether the application really requires the slight reduction in delay. When Nagle is turned off, using the macro tcp_set_nonagle(&socket), transmit processing is changed so that TCP tries to transmit a packet for each call of a socket write function such as sock_fastwrite(). If Nagle is on (which is the default state or can be set using tcp_set_nagle(&socket)) a new packet will only be sent if there is no outstanding unacknowledged data. Thus, on a slow network where acknowledgements from the peer take a substantial amount of time to arrive, fewer packets will be sent because there is a greater chance that there is some unacknowledged data. The difference may be illustrated by the following example: suppose that a TCP socket connection is currently established and quiescent (i.e., there is no outstanding data to be acknowledged; everything is up-to-date). The network round-trip-time is 550ms. The application writes ten single characters to the socket, at 100ms intervals each. With Nagle turned off, ten packets will be sent at approximately 100ms intervals. Each packet will contain a 40-byte header (IP and TCP) with a single byte of data. A total of 410 bytes will be sent. With Nagle on, the first character written at time zero will cause a 41-byte packet to be sent. The acknowledgment of this first packet will not arrive for another 550ms. In the meantime, the application writes an additional 5 characters at 100ms intervals. Since there is outstanding unacknowledged data (the first character) these charac60 TCP/IP Users Manual

ters are not sent immediately. They are buffered, waiting for an acknowledgment from the peer. When the first characters acknowledgment comes in at 550ms, there is no outstanding unacked data; the additional 5 characters have not yet been sent so they do not count as unacked data. Now the TCP stack will send the 5 additional characters in a single packet at approximately t=550ms. While that packet is in transit, 4 more characters are written by the application. Again, these characters will be buffered since characters 2 through 6 have not been acknowledged. Only when the next acknowledgment is received will these 4 characters be sent. The total number of packets sent is 3, with 1, 5 and 4 bytes of data. This translates to 130 bytes in total. Obviously, the total number of bytes transmitted, including overhead, is far less when Nagle is used (130 compared with 410 bytes). One can also examine how this looks from the point of view of the peer. In the non-Nagle case, each character is received 275ms after it was transmitted (we assume that the one-way trip is half of the RTT). The last character is received at t=1175ms (with the reference t=0 taken as the first character transmission time). The acknowledgment of the last character, which completes the transaction, is received at t=1400ms. In the Nagle case, the last character is received at t=1375 and the final acknowledgment at t=1650. In this example, the peer received all 10 characters 200ms later when Nagle was used. It can be seen that at a slight cost in increased delay, a great saving in total data transmission was made. If the above example was extended to hundreds or thousands of characters, then the additional delay would remain constant at a few hundred ms, whereas the network bandwidth would be better utilized by a factor approaching five! In conclusion, leave Nagle on unless you absolutely must have the lowest delay between transmission and reception of data. If you turn Nagle off, ensure that your application is disciplined enough to write the largest blocks it can. For example, if you have to send an 8-byte value (as a unit), construct the full 8 bytes as a single block then write them all in a single sock_fastwrite() call, rather than calling sock_fastwrite() with two 4-byte calls or, worse, 8 single byte calls. A useful alternative to turning Nagle off is to control packetization using calls to sock_flush(), sock_noflush() and sock_flushnext(). These functions allow the application fairly fine control over when TCP sends packets. Basically, sock_noflush() is used to set a lock on the socket that prevents TCP from sending packets containing new data. After sock_noflush(), you can call sock_fastwrite() or other write functions. The new data will not be sent until the socket is unlocked with a call to sock_flush(). sock_flushnext() unlocks the socket, but TCP does not send any data until the next write function is called.

4.2.2 Time-Out Settings


There are many time-out settings in TCP. These are necessary because the TCP socket needs to be able to take meaningful actions when things take longer than expected. For good performance, it is also sometimes necessary for the socket to delay slightly some action that it could otherwise perform immediately. The time-out settings currently apply to all sockets; they cannot be applied selectively because they are in the form of macro constants. In general, you can improve overall TCP performance by reducing some of the time-out settings, however there is a law of diminishing returns, and you can also start to reduce overall efficiency.
Chapter 4: Optimizing TCP/IP Performance 61

What may be good settings for a local Ethernet connection may be very poor for an Internet connection. Note that if you optimize time-out settings for a particular network environment, you will need to document this so that your end-users do not inadvertently use your application in the wrong sort of environment. For this reason, it is best to use the default settings for general-purpose applications, since the defaults work well in worst-case settings without affecting best-case performance unduly. TCP is internally adaptive to network bandwidth and RTT, which are the main variables. Some of the time-out settings only apply to an initial guess of the network characteristics; TCP will converge to the correct values in a short time. Specifying a good initial guess will help TCP in the initial stages of establishing a socket connection. 4.2.2.1 Time-Out Setting Constants The following constants can be #defined before including dcrtcp.lib. They specify various time intervals that have a bearing on connection performance.

RETRAN_STRAT_TIME
This defaults to 10ms. It specifies the minimum time interval between testing for retransmissions of data for a particular TCP socket. This not only provides an upper bound for packet transmission rate, but also cuts down on CPU overhead. Since retransmissions are basically driven from tcp_tick(), the less time used in tcp_tick() processing the more time is left for your application. Note that the actual minimum retransmit interval is defined by TCP_MINRTO; this setting only affects the testing interval. Retransmissions are only required when there is an unexpected surge in network congestion, which causes packets to be delayed well beyond the average or even dropped. It is not recommended to reduce this setting, but you could increase it to about 100ms to cut down on tcp_tick() overhead without materially affecting most applications.

TCP_MINRTO
Defaults to 250ms. This specifies the actual minimum time between TCP retransmissions. Reducing this will not affect performance in a properly functioning network, and may in fact worsen efficiency. Only in a network that is dropping a high percentage of packets will this setting have any real effect. On local Ethernet connections, genuine packet drops will be practically non-existent. The most likely cause of delays is if a host CPU is tied up and unable to perform network processing. On Internet connections, setting a retransmit time shorter than 250ms is just as likely to worsen the congestion which is causing packets to be dropped in the first place. The only case where this value might be profitably reduced is the case of a point-topoint link where there is a lot of packet loss (maybe because the RS232 wiring is routed near an industrial welder). In this case, any packet loss may be assumed to be because of noise or interference, not because of router congestion. In the Internet, most packet loss is because of router congestion, in which case there is nothing to be gained by reducing TCP_MINRTO. Another reason for not reducing this setting is that modern TCP/IP implementations

62

TCP/IP Users Manual

only acknowledge every 2nd packet received (or after a short time-out - see TCP_LAZYUPD). Normally, this will happen within the 250ms time interval, so there will be no unnecessary retransmission.

TCP_TWTIMEOUT
This defaults to 2000ms (2 seconds). This is one area where embedded system requirements conflict somewhat with recommendations in the standards documents. The time-wait time-out is a waiting period that is necessary when a socket is closed. This waiting period is supposed to be twice the maximum lifetime of any packet in the network. The maximum packet lifetime is 255 seconds, so the time-wait time-out should be about 8 minutes. The purpose of the waiting time is to allow both ends of the connection to be satisfied that their respective peer has agreed to the close and acknowledged it. This wait time only affects the closed socket i.e., the unique socket combination of IP addresses and port numbers. It means that when a socket is closed, the same socket cannot be re-opened until at least 8 minutes have passed. This is usually no problem for systems that have large memories to hold the state of recently closed sockets. For an embedded system, which has a limited pool of sockets and limited memory for storing connection states, this wait time is inconvenient since the socket structure cannot be re-used until the time-wait period has expired. The default time-wait period is thus set to 2 seconds in the Dynamic C TCP/IP libraries. This will work perfectly well for local Ethernet connections, where the maximum packet lifetime is of the order of milliseconds. For Internet connections, this may be a bit short, but will generally be satisfactory. If in fact the time-wait period is too short, the worst that will happen is that one of the peers will be unsure about whether the other end got the last segment of data, and confusion may happen if old packets (from this connection) happen to arrive after the close. This latter case is unlikely to happen, but if it does then it will eventually be resolved when the socket connection process times out. If you want your application to be more robust, you can increase this value. 8 minutes is an extremely conservative value. Most implementations shorten this to 2 minutes or 30 seconds, since packets are extremely unlikely to survive more than 15 seconds. Note that this value is only used if you do not specify the tcp_reserveport() option for the local port of a passively opened connection. If you specify reserveport, then the time-wait period is set to zero.

Chapter 4: Optimizing TCP/IP Performance

63

TCP_LAZYUPD
This defaults to 5ms, and is used for several purposes. The first use is to reschedule transmission attempts that could not be processed owing to local resource shortages. For example, if a previous packet is still being transmitted via a slow PPP interface, the current packet may need to be delayed. Similarly, the Ethernet hardware can be busy. In these cases, the TCP stack needs to try again a short time later. The second use is to allow time for further information to come in from the network before transmitting otherwise empty packets. TCP has two main reasons for transmitting packets with no data content. The first is acknowledgement of incoming data when we have nothing to send, and the other is to update our receive window to the peer. The receive window tells the peer how much data it can transmit which we can store in our socket receive buffer. This window needs to be updated not only when we receive data, but also when the application reads data out of the receive buffer. Rather than send these empty packets as soon as possible, it is often profitable to wait a short time. In the case of window updates, this can allow the application to write some data after the read which updated the window. The data can be sent with the window update, which improves efficiency because one packet can do the work of two. For receive data acknowledgements, the same trick can be applied i.e., piggy-backing on some additional data. These optimizations can be taken advantage of quite often with most applications, so it is worth while specifying the lazy update time-out to be at least a few ms. Lowering the lazy update interval can slightly improve latency and throughput on high-speed (i.e., local Ethernet) connections.

4.2.3 Reserved Ports


As mentioned in the TCP_TWTIMEOUT description, you can specify that certain TCP port numbers have the special property of being reserved. If a port is reserved, it has two effects:

A number of pending connections can be queued while a socket connection is established.


The pending connections form a FIFO queue, with the longest-outstanding pending connection becoming active after the current connection is closed.

The time-wait time-out is truncated when the current connection is closed.


Together, these increase the performance of passively-opened sockets, which are designed to implement server functions such as FTP and HTTP servers. Reserving a port has no effect on actively opened sockets (i.e., clients), and does not affect its performance during the life of each connection. The functions tcp_reserveport() and tcp_clearreserve() respectively enable and disable a TCP port number from being treated in this manner.

64

TCP/IP Users Manual

4.2.4 Type of Service (TOS)


Type Of Service is an IP (Internet Protocol) header field that causes routers in the Internet to handle packets according to the specified service level. TOS has not been widely deployed in the past, but recently Internet routers have been able to take advantage of the TOS field. TOS generally takes one (and only one) of a pre-specified number of values. The currently available values are:

IPTOS_DEFAULT - the default, used when none of the following are obviously applicable.

IPTOS_CHEAP - minimize monetary cost. Used for bulk transfers where speed or reliability are not of concern, and you are paying by the packet.

IPTOS_RELIABLE - maximize reliability. IPTOS_CAPACIOUS - maximize throughput. IPTOS_FAST - minimize delay. IPTOS_SECURE - maximize security.

IP does not guarantee that the TOS setting will improve the objective performance, however, it at least guarantees that performance will not be any worse than if the default TOS was selected. In other words, it doesnt hurt to specify TOS, and it may even help! TOS can be set on a packet-by-packet basis; however, the TCP stack only allows a TOS to be set for a socket (TCP or UDP) which is used for all packets until changed. The function sock_set_tos() is used to set the TOS field.

4.2.5 ARP Cache Considerations


ARP (Address Resolution Protocol) is only relevant for non-PPPoE Ethernet, not PPP interfaces. Although it works in the background, mainly to translate IP addresses into Ethernet MAC addresses, there are some considerations which apply to TCP (and UDP) performance. There is a limited size cache of address mapping entries, known as the ARP Table. The cache is necessary in order to avoid network traffic each time a socket connection is established. It must be sized appropriately to avoid cache misses as much as possible. If the controller board is to be used exclusively in server mode, i.e., TCP sockets opened passively, then the cache does not have to be very big. If, on the other hand, the controller is going to actively establish sessions with a number of hosts, then the cache should be big enough to contain an entry for each host such that entries do not get pushed out for at least a few minutes. The ARP Table also contains special entries for routers that are on the local Ethernet. These entries are important, since they represent entries for all hosts that are not on the local LAN segment subnet. The default sizing rule for the ARP Table allocates an entry for each interface (including point-topoint) plus 5 entries for each Ethernet interface in use. The single entry for each interface is basically reserved for routers, on the assumption that each interface will probably require a router to allow connections to hosts which are farther afield. The additional 5 entries (for Ethernet) are for non-router hosts that the controller board will need to talk to.

Chapter 4: Optimizing TCP/IP Performance

65

This implies that 5 connections to hosts on the Ethernet subnet can be supported simultaneously, without any of the entries being pushed out. If the table is full, connection to a 6th host can be made, with the least-recently-used host entry being pushed out to make room. If your application connects with, say, ten hosts in random order, it is likely that the ARP Table will need to be increased in size. If in doubt, increase the table size, since each entry only takes up about 32 bytes.

4.3 Writing a Fast UDP Request/Response Server


UDP is a lightweight protocol wrapper that adds port number multiplexing and checksums to basic IP packets. Being lightweight, it is capable of being very fast, with low CPU overhead. UDP is often selected for custom application protocols that do not need the reliable, stream-oriented, connections of TCP. UDP is connectionless, however, application designers can think in terms of client-server or transaction-based programming. A popular design for UDP servers is to have the controller board listen for incoming datagrams. Each incoming message is processed and an immediate reply is sent. It is left up to the client to retransmit messages if it did not receive a reply in the expected time frame. The server, however, is extremely simple to implement, which allows it to serve more clients than a TCP-based server could manage. Starting with Dynamic C 7.30, a data handler facility has been added to UDP (as well as TCP) sockets. The data handler is especially efficient for UDP, since it allows the datagram to be processed without any copying to the socket buffer. The UDP data handler is a callback function whose address is supplied on the udp_extopen() call. For simple request/response applications, the only application requirements are to define the data handler, and call tcp_tick() repeatedly in a loop after setting up the TCP/IP stack and opening the UDP socket. The sample program Samples\tcpip\udp\udp_echo_dh.c shows how to implement a simple UDP echo server using the technique described in this section.

4.4 Tips and Tricks for TCP Applications


This section contains miscellaneous suggestions for getting the most out of your TCP-based applications. Application design requirements that affect TCP performance include:

the responsiveness and throughput requirements of the application how often tcp_tick() can be called whether socket is used in ASCII or binary mode whether multitasking or big loop programming style.

The list of application types on page 57 is used as a basis for discussion. Your application may neatly fit into one of these categories, or it may be a combination of several. In either case, you should try to follow the programming guidelines unless you are fairly experienced with the Dynamic C TCP/IP libraries.

66

TCP/IP Users Manual

4.4.1 Bulk Loader Applications


This type of application is idle (from the TCP/IP point of view) most of the time, but this is punctuated by periods of intensive data transfer. Applications which exhibit this characteristic include data loggers and file transfer agents e.g. FTP server or client. Sending email via SMTP also comes under this category. The main application requirement is good utilization of the available bandwidth i.e., highest throughput. This is achieved by using the largest practical buffer sizes, processing data in the largest possible chunks, and minimizing data copying. Since the Rabbit processor is CPU-bound when dealing with high speed transfers (over Ethernet), every time the data is handled it reduces the ultimate throughput. The Nagle algorithm should be left ON. Time-outs should be set to generously high values to avoid unnecessary retransmissions. The TOS should be set to IPTOS_CAPACIOUS. Bulk TCP transfers are most efficient when the packet size is the largest possible. The largest packet size is limited to the MTU size of the network connection. You can assume that 600 bytes is a reasonable MTU for Internet connections. You can use up to 1500 for all supported interface types (except PPPoE, which is limited to 1492), however it is best to use 600 if Internet connections are expected. If the Internet MTU is in fact less than the expected value, then packets may become fragmented, which lowers efficiency. You cannot do much about this except reduce the MTU. When the MTU is determined, the maximum TCP packet data length will usually be the MTU minus 40. The 40 bytes are for the IP and TCP header overhead. For a 600 byte MTU, the maximum TCP data segment size will be 560. Thus, TCP performance will be best if data is handled in multiples of 560 bytes. It is not quite this simple, however. When a TCP connection is opened, both sides can agree to use different data segment sizes than the default. Generally, whichever side has the smallest MTU will place a limit on the segment size. This is negotiated via the TCP MSS (Maximum Segment Size) option. In your program, rather than hard-coding the optimum chunk size, you can define a symbol as follows: #define TCP_CHUNK_SIZE (MAX_MTU - 40) where MAX_MTU is a symbol defined by the library to be the actual MTU in effect. For multiple interfaces, it is probably better to use the minimum value of any interface. You can find out the current MTU for an interface using ifconfig(iface, IFG_MTU, &mtu, IFS_END) which will read the MTU for interface iface into the integer variable mtu. Most of the time, the TCP socket MSS will be equal to the fixed value above. In cases where it is smaller, there will not be a noticeable decrease in efficiency. Once you have determined the appropriate chunk size, use sock_awrite() or sock_axwrite() (for extended memory data) with the specified chunk size, except possibly for the last chunk. sock_awrite() and friends are available starting with Dynamic C 7.30. They have the advantage that the data is completely buffered, or not at all. sock_fastwrite() may buffer less than the requested amount, which means that your application needs to keep track of the current position in the data being sent. sock_awrite() does not do things by halves, so it is easier to keep track in the application. Because it will not do small data moves, it is also slightly more efficient in terms of CPU time.
Chapter 4: Optimizing TCP/IP Performance 67

4.4.2 Casual Server Applications


A casual server is a term we use for applications that need to respond to occasional requests for information, or commands, without large data transfers. Although the amount of data transfer is limited, the application still needs to be as responsive as possible. Example applications of this type include machine, building and power controllers. Interactive servers are also included, such as telnet. The main goal here is to achieve low latency.

4.4.3 Master Controller Applications


Master controllers are responsible for coordinating access to a number of other devices (via TCP/IP or other types of communication) or acting as an access concentrator. Data transfer may be low to moderate. Latency should be minimized.

4.4.4 Web Server Applications


The TCP/IP libraries include web server software. HTTP.LIB takes advantage of the TCP library to get good performance. Your application can still affect web server performance, since it may be responsible for generating content via CGI callback functions. Web servers have much the same characteristics as bulk loaders, however, they are such a common case that they deserve special treatment.

4.4.5 Protocol Translator Applications


A protocol translator basically converts between a TCP data stream and some other type of data stream, for example asynchronous serial data. The data may flow in either or both directions. This type of application has the most stringent requirements on both throughput and latency. This is because the incoming stream may not be amenable to any sort of flow control: it is necessary for TCP to keep up with a possibly high data rate. Also, the more timely the transmission of data, the more useful the protocol translator.

68

TCP/IP Users Manual

5. Network Addressing: ARP & DNS


ARP (Address Resolution Protocol) and DNS (Domain Name System) perform translations between various network address formats. ARP converts between IP addresses and (usually) Ethernet hardware addresses. DNS converts between human-readable domain names such as ftp.mydomain.org and IP addresses. ARP and DNS are not closely related protocols, but they are lumped together in this chapter for convenience. In the Dynamic C TCP/IP libraries, ARP.LIB handles ARP proper, as well as router (gateway) functionality.

5.1 ARP Functions


ARP (Address Resolution Protocol) is used on non-PPPoE Ethernet interfaces. ARP is used to determine the hardware address of network interface adapters. Most of the ARP functionality operates in the background and is handled by the TCP/IP libraries. Most applications should not need to deal with ARP, and indeed some of the ARP functions are quite complex to use correctly. Nevertheless, there are some useful debugging functions included in ARP.LIB. Starting with Dynamic C 7.20, the internal ARP processing was converted to non-blocking style. This has no direct impact on applications, except that there will be lower maximum latency in tcp_tick() calls. The ARP functions are all named starting with _arp, arpcache, arpresolve, or router. router_printall() is a useful function for debugging router table problems, for example in the case where connections to hosts which are not on local subnets appear to be failing.

5.2 Configuration Macros for ARP


ARP_LONG_EXPIRY
Number of seconds that a normal entry stays current. Defaults to 1200.

ARP_SHORT_EXPIRY
Number of seconds that a volatile entry stays current. Defaults to 300.

ARP_PURGE_TIME
Number of seconds until a flushed entry is actually deleted. Defaults to 7200.

Chapter 5: Network Addressing: ARP & DNS

69

ARP_PERSISTENCE
Number of retries allowed for an active ARP resolve request to come to fruition. Default s to 4. If no response is received after this many requests, then the host is assumed to be dead. Set to a number between 0 and 7. This number relates to the total time spent waiting for a response as follows: timeout = 2(ARP_PERSISTENCE+1) - 1 e.g. for 0 the time-out is 1 second. For 4 it is 31 seconds. For 7 it is 255 seconds. If you set this to 8 or higher, then ARP will persist forever, retrying at 128 second intervals.

ARP_NO_ANNOUNCE
Configuration items not defined by default. Do not announce our hardware address at sock_init(). This macro is undefined by default. Do not uncomment it in NET.LIB. Instead, define it in your mainline C program before including the networking libraries.

ARP_CONFLICT_CALLBACK
Define a function to call in case of IP address conflict. This function takes a arp_Header pointer as the first and only parameter. It should return one of

0: do not take any action 0xFFFFFFFF : abort all open sockets with NETERR_IPADDR_CONFLICT other: new IP address to use. Open sockets are aborted with
NETERR_IPADDR_CHANGE. This macro is undefined by default. Do not uncomment it in NET.LIB. Instead, define it in your mainline C program before including the networking libraries.

ARP_TABLE_SIZE
Define to the number of ARP table entries. The default is set to the number of interfaces, plus 5 entries for every non-PPPoE Ethernet interface. The maximum allowable value is 200.

ARP_ROUTER_TABLE_SIZE
Define the maximum number of routers. Defaults to the number of interfaces, plus an extra entry for each non-PPPoE Ethernet.

70

TCP/IP Users Manual

5.3 DNS Functions


Starting with Dynamic C 7.05, non-blocking DNS lookups are supported. Prior to DC 7.05, there was only the blocking function, resolve(). Compatibility has been preserved for resolve(), MAX_DOMAIN_LENGTH , and DISABLE_DNS. The application program has to do two things to resolve a host name: 1. Call resolve_name_start() to start the process. 2. Call resolve_name_check() to check for a response. Call resolve_cancel()to cancel a pending lookup.

5.4 Configuration Macros for DNS Lookups


DISABLE_DNS
If this macro is defined, DNS lookups will not be done. The DNS subsystem will not be compiled in, saving some code space and memory.

DNS_MAX_RESOLVES
4 by default. This is the maximum number of concurrent DNS queries. It specifies the size of an internal table that is allocated in xmem.

DNS_MAX_NAME
64 by default. Specifies the maximum size in bytes of a host name that can be resolved. This number includes any appended default domain and the NULL-terminator. Backwards compatibility exists for the MAX_DOMAIN_LENGTH macro. Its value will be overridden with the value DNS_MAX_NAME if it is defined. For temporary storage, a variable of this size must be placed on the stack in DNS processing. Normally, this is not a problem. However, for C/OS-II with a small stack and a large value for DNS_MAX_NAME, this could be an issue.

DNS_MAX_DATAGRAM_SIZE
512 by default. Specifies the maximum length in bytes of a DNS datagram that can be sent or received. A root data buffer of this size is allocated for DNS support.

DNS_RETRY_TIMEOUT
2000 by default. Specifies the number of milliseconds to wait before retrying a DNS request. If a request to a nameserver times out, then the next nameserver is tried. If that times out, then the next one is tried, in order, until it wraps around to the first nameserver again (or runs out of retries).

Chapter 5: Network Addressing: ARP & DNS

71

DNS_NUMBER_RETRIES
2 by default. Specifies the number of times a request will be retried after an error or a time-out. The first attempt does not constitute a retry. A retry only occurs when a request has timed out, or when a nameserver returns an unintelligible response. That is, if a host name is looked up and the nameserver reports that it does not exist and then the DNS resolver tries the same host name with or without the default domain, that does not constitute a retry.

DNS_MIN_KEEP_COMPLETED
10000 by default. Specifies the number of milliseconds a completed request is guaranteed to be valid for resolve_name_check(). After this time, the entry in the internal table corresponding to this request can be reused for a subsequent request.

DNS_SOCK_BUF_SIZE
1024 by default. Specifies the size in bytes of an xmem buffer for the DNS socket. Note that this means that the DNS socket does not use a buffer from the socket buffer pool.

72

TCP/IP Users Manual

6. IGMP and Multicasting


The Internet Group Management Protocol (IGMP) and multicasting are supported by the Dynamic C TCP/IP stack starting with version 7.30.

6.1 Multicasting
Multicasting is a form of limited broadcast. UDP is used to send datagrams to all hosts that belong to what is called a host group. A host group is a set of zero or more hosts identified by the same destination IP address. The following statements apply to host groups.

Anyone can join or leave a host group at will. There are no restrictions on a hosts location. There are no restrictions on the number of members that may belong to a host group. A host may belong to multiple host groups. Non-group members may send UDP datagrams to the host group.

Multicasting is useful when data needs to be sent to more than one other device. For instance, if one device is responsible for acquiring data that many other devices need, then multicasting is a natural fit. Note that using multicasting as opposed to sending the same data to individual devices uses less network bandwidth.

6.1.1 Multicast Addresses


A multicast address is a class D IP address, i.e., the high-order four bits are 1110. Addresses range from 224.0.0.0 to 239.255.255.255. The address 224.0.0.0 is guaranteed not to be assigned to any group, and 224.0.0.1 is assigned to the permanent group of all IP hosts (including gateways). This is used to address all multicast hosts on a directly connected network.

6.1.2 Host Group Membership


Any datagram sent to a multicast address is received by all hosts that have joined the multicast group associated with that address. A host group is joined automatically when the remote IP address passed to udp_open() is a valid multicast address. A host group may also be joined by a call to multicast_joingroup(). Leaving a host group is done automatically when udp_close() is called. Like joining, leaving a group may be done explicitly by an application by calling an API function, in this case: multicast_leavegroup().

6.2 IGMP
As long as all multicast traffic is local (i.e., on the same LAN) IGMP is not needed. IGMP is used for reporting host group memberships to any routers in the neighborhood. The library IGMP.LIB conforms to RFC 2236 for IGMPv2 hosts.

Chapter 6: IGMP and Multicasting

73

6.3 Multicast Macros


As mentioned above, the use of IGMP is not required for multicast support on a LAN. You may select only multicast support by defining USE_MULTICAST.

USE_MULTICAST
This macro will enable multicast support. In particular, the extra checks necessary for accepting multicast datagrams will be enabled and joining and leaving multicast groups (and informing the Ethernet hardware about it) will be added.

USE_IGMP
If this macro is defined, the USE_MULTICAST macro is automatically defined. This macro enables sending reports on joining multicast addresses and responding to IGMP queries by multicast routers. Unlike USE_MULTICAST, this macro must be defined to be 1 or 2. This indicates which version of IGMP will be supported. Note, however, that both version 1 and 2 IGMP clients will work with both version 1 and 2 IGMP routers. Most users should just choose version 2.

IGMP_V1_ROUTER_PRESENT_TIMEOUT
Defaults to 400. When IGMPv2 is supported, a timer is set to this many seconds every time the board sees an IGMPv1 message from an IGMP router. As long as there is time left on the timer, the board acts as an IGMPv1 host. If the timer expires, the board returns to acting as an IGMPv2 host.

IGMP_UNSOLICITED_REPORT_INTERVAL
Defaults to 100 deciseconds (10 seconds). This value is specified in deciseconds. It determines the maximum random interval between the initial join report for a multicast group and the second join report.

74

TCP/IP Users Manual

7. Function Reference
This section contains descriptions for all user-callable functions in DCRTCP.LIB. Starting with Dynamic C 7.05, DCRTCP.LIB is a light wrapper around

DNS.LIB IP.LIB NET.LIB TCP.LIB UDP.LIB.

This update requires no changes to existing code. Descriptions for select user-callable functions in:

ARP.LIB ICMP.LIB BSDNAME.LIB IGMP.LIB XMEM.LIB

are also included here. Note that ARP.LIB, ICMP.LIB and BSDNAME.LIB are automatically #used from DCRTCP.LIB. Functions are listed alphabetically and by category grouped by the task performed.

Chapter 7: Function Reference

75

_abort_socks
int _abort_socks( byte reason, byte iface );
DESCRIPTION

Abort all open TCP and UDP sockets. This routine may be called if the network becomes unavailable, for example because a DHCP address lease expired or because an IP address conflict was encountered. This function is generally intended for internal library use, but may be invoked by applications in special circumstances.
PARAMETERS

reason

Reason code. A suitable NETERR_* constant as defined in NETERRNO.LIB. This code is set as the error code for each socket that was affected. Specific interface on which active connections are to be aborted, or pass IF_ANY to abort connections on all active interfaces.

iface

RETURN VALUE

0
SEE ALSO

sock_abort, sock_error

76

TCP/IP Users Manual

arpcache_create
ATHandle arpcache_create( longword ipaddr );
DESCRIPTION

Create a new entry in the ARP cache table for the specified IP address. If a matching entry for that address already exists, then that entry is returned. Otherwise, a new entry is initialized and returned. If a new entry is created, then an old entry may need to be purged. If this is not possible, then ATH_NOENTRIES is returned.
PARAMETER

ipaddr
RETURN VALUE

IP address of entry.

Positive value: Success. ATH_NOENTRIES: No space is available in the table, and none of the entries could be purged because they were all marked as permanent or router entries.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

77

arpcache_flush
ATHandle arpcache_flush( ATHandle ath );
DESCRIPTION

Mark an ARP cache table entry for flushing. This means that the given table entry will be the first entry to be re-used for a different IP address, if necessary. Any entry (including permanent and router entries) may be flushed except for the broadcast entry.
PARAMETER

ath
RETURN VALUE

ARP table handle obtained from e.g., arpcache_search().

Positive value: Success. ATH_UNUSED: The table entry was unused. ATH_INVALID: the ath parameter was not a valid handle. ATH_OBSOLETE: The given handle was valid, but obsoleted by a more recent entry. No change made.
LIBRARY

ARP.LIB

78

TCP/IP Users Manual

arpcache_hwa
ATHandle arpcache_hwa( ATHandle ath, byte *hwa );
DESCRIPTION

Copy the Ethernet (hardware) address from the given ARP cache table entry into the specified area.
PARAMETERS

ath hwa
RETURN VALUE

ARP cache table entry. Address of where to store the hardware address (6 bytes).

Positive value: Handle to the entry. ATH_UNUSED: The table entry was unused. ATH_INVALID: The ath parameter was not a valid handle. ATH_OBSOLETE: The given handle was valid, but obsoleted by a more recent entry. No change made.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

79

arpcache_iface
ATHandle arpcache_iface( ATHandle ath, byte *iface );
DESCRIPTION

Copy the interface number from the given ARP cache table entry into the specified area. If the ath parameter refers to a broadcast or loopback entry, then *iface is set to IF_DEFAULT (and ATH_INVALID is returned, since we can't really determine which of the interfaces to broadcast from).
PARAMETERS

ath iface
RETURN VALUE

ARP cache table entry. Address of where to store the interface number (1 byte).

Positive value: Handle to the entry. ATH_UNUSED: The table entry was unused. ATH_INVALID: The ath parameter was not a valid handle, or was a broadcast, multicast or loopback handle. ATH_OBSOLETE: The given handle was valid, but obsoleted by a more recent entry.
LIBRARY

ARP.LIB

80

TCP/IP Users Manual

arpcache_ipaddr
ATHandle arpcache_ipaddr( ATHandle ath, longword *ipaddr );
DESCRIPTION

Copy the IP address from the given ARP cache table entry into the specified area. If the ath parameter refers to a broadcast entry, then the subnet broadcast IP is returned.
PARAMETERS

ath ipaddr
RETURN VALUE

ARP cache table entry. Address of where to store the IP address (4 bytes).

Positive value: Handle to the entry. ATH_UNUSED: The table entry was unused. ATH_INVALID: The ath parameter was not a valid handle, or was a point-point, broadcast, multicast or loopback handle. ATH_OBSOLETE: The given handle was valid, but obsoleted by a more recent entry.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

81

arpcache_load
ATHandle arpcache_load( ATHandle ath, byte *hwa, byte iface, word flags, byte router_used );
DESCRIPTION

Load an entry in the ARP cache table. The entry must have been created using arpcache_create(), or be an existing valid entry located via arpcache_search(). This function is primarily intended for internal use by the ARP library, although advanced applications could also use it. Most applications should not need to call this function directly.
PARAMETERS

ath hwa

Handle for the entry. Hardware (Ethernet) address, or NULL. Pass NULL if the current hardware address is not to be changed. Interface to use (IF_DEFAULT to use default, or not change current setting). Flags for entry: one or more of the following values, OR'd together:

iface

flags

ATE_PERMANENT: permanent entry ATE_RESOLVING: initiate network resolve for this entry
(hwa is ignored if this flag is set)

ATE_RESOLVED: this entry now resolved ATE_ROUTER_ENT: this is a router entry ATE_FLUSH: mark this entry for flush ATE_VOLATILE: set short timeout for this entry ATE_ROUTER_HOP: this entry uses the specified router as the first hop. hwa ignored.

ATE_REDIRECTED: this entry redirected by ICMP.


Only one of ATE_ROUTER_ENT or ATE_ROUTER_HOP should be set. For either of these, the next parameter indicates the router table entry to use. Only one of ATE_RESOLVING or ATE_RESOLVED should be set. router_used Router table entry. Only used if one of ATE_ROUTER_ENT or ATE_ROUTER_HOP is set in the flags parameter.

82

TCP/IP Users Manual

arpcache_load (continued)
RETURN VALUE

Positive value: Success. ATH_NOROUTER: The specified router entry number is invalid. This can be because the router_used parameter is bad, or because the router entry has a mismatching ATH. ATH_INVALID: Invalid table handle passed (or unused entry). ATH_OBSOLETE: The given handle was valid, but obsoleted by a more recent entry. No change made.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

83

arpcache_search
ATHandle arpcache_search( longword ipaddr, int virt );
DESCRIPTION

Return handle that refers to the ARP cache table entry for the given IP address. This does not do any resolving. It only consults the existing cache entries. The returned handle is guaranteed to be valid at least until the next call to tcp_tick(). Usually the handle will be valid for considerably longer, however it is possible for the handle to become obsolete if the cache entry is re-used for a different address. The caller should be able to deal with this possibility. The entry returned for the broadcast address is guaranteed to be permanent.
PARAMETERS

ipaddr

IP address to locate in the cache. This may be -1L to locate the broadcast entry or our own IP address to return the "loopback" entry. 0: Do not return the broadcast or loopback entries. 1: Allow the broadcast or loopback entries.

virt

RETURN VALUE

Positive value: Handle to the entry. ATH_NOTFOUND: No entry exists for the given IP address.
LIBRARY

ARP.LIB

84

TCP/IP Users Manual

_arp_resolve
int _arp_resolve( longword ina, eth_address *ethap, int nowait );
DESCRIPTION

Gets the Ethernet address for the given IP address. This function is deprecated starting in Dynamic C 7.20.
PARAMETERS

ina ethap nowait

The IP address to resolve to an Ethernet address. The buffer to hold the Ethernet address. If 0, return within 750 ms; else if !0 wait up to 5 seconds trying to resolve the address.

RETURN VALUE

1: Success. 0: Failure.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

85

arpresolve_check
ATHandle arpresolve_check( ATHandle ath, longword ipaddr );
DESCRIPTION

Check up on status of resolve process initiated by arpresolve_start(). This function should be called regularly to ensure that an ARP table handle is pointing to the correct entry, and that the entry is still current. This caller must call tcp_tick() if spinning on this function.
PARAMETERS

ath ipaddr

ARP Table Handle obtained from arpresolve_start(). IP address specified to arpresolve_start(). If this is zero, no check is performed. Otherwise, the ARP table entry is checked to see that it is the correct entry for the specified IP address.

RETURN VALUE

Positive value: Completed successfully. The return value will be the same as the ath parameter. ATH_AGAIN: Not yet completed, try again later. ATH_FAILED: Completed in error. Address cannot be resolved because of a network configuration problem. ATH_TIMEDOUT: Resolve timed out. No response from addressee within the configured time limit. ATH_INVALID: The ath parameter was not a valid handle|. ATH_OBSOLETE: The given handle was valid, but obsoleted by a more recent entry. Restart using arpresolve_start(). ATH_MISMATCH: The ipaddr parameter was not zero, and the IP address does not match the table entry.
LIBRARY

ARP.LIB

86

TCP/IP Users Manual

arpresolve_ipaddr
longword arpresolve_ipaddr( ATHandle ath );
DESCRIPTION

Given an ARP table handle, return the IP address of the corresponding table entry.
PARAMETER

ath
RETURN VALUE

ARP Table Handle obtained from e.g., router_for().

0: An error occurred, such as an invalid or obsolete handle. 0xFFFFFFFF: The handle refers to either the broadcast address, or to a point-to-point entry whose IP address is not defined. Else: An IP address. This may be 127.0.0.1 for the loopback entry.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

87

arpresolve_start
ATHandle arpresolve_start( longword ipaddr );
DESCRIPTION

Start resolve process for the given IP address. This may return immediately if the IP address is in the ARP cache table and still valid. Otherwise, if the IP address is on the local subnet then an ARP resolve request is issued through the appropriate interface. If the address is not on the local subnet, then a router table entry is used and no network activity is necessary (unless the router itself is not resolved, in which case its resolution commences).
PARAMETER

ipaddr
RETURN VALUE

IP address of host whose hardware address is to be resolved.

Positive value: Success. The value is actually the ATH of the ARP cache table entry which is (or will be) used. This value should be passed to subsequent calls to arpresolve_check(). ATH_NOENTRIES: No space is available in the table, and none of the entries could be purged, because they were all marked as permanent or router entries. ATH_NOROUTER: No router ("gateway") is configured for the specified address, which is not on the local subnet.
LIBRARY

ARP.LIB

88

TCP/IP Users Manual

aton
longword aton( char *text );
DESCRIPTION

Converts [a.b.c.d] or a.b.c.d to a 32 bit long value.


PARAMETER

text
RETURN VALUE

Pointer to string that holds the IP address to convert.

0: Error, string has invalid format. >0: Success, long value of IP address.
LIBRARY

IP.LIB

Chapter 7: Function Reference

89

_chk_ping
longword _chk_ping( longword host_ip, longword *sequence_number);
DESCRIPTION

Checks for any outstanding ping replies from host. _chk_ping should be called frequently with a host IP address. If an appropriate packet is found from that host IP address, the sequence number is returned through *sequence_number. The time difference between our request and their response is returned in milliseconds.
PARAMETERS

host_ip

IP address to receive ping reply from. Sequence number of reply.

sequence_number
RETURN VALUE

Time in milliseconds from the ping request to the hosts ping reply. If _chk_ping returns 0xffffffffL, there were no ping receipts on this current call.
LIBRARY

ICMP.LIB
SEE ALSO

_ping, _send_ping

90

TCP/IP Users Manual

dhcp_acquire
int dhcp_acquire( void );
DESCRIPTION

This function acquires a DHCP lease that has not yet been obtained, or has expired, or was relinquished using dhcp_release(). Normally, DHCP leases are renewed automatically, however if the DHCP server is down for an extended period then it might not be possible to renew the lease in time, in which case the lease expires and TCP/IP should not be used. When the lease expires, tcp_tick() will return 0, and the global variable for the IP address will be reset to 0. At some later time, this function can be called to try to obtain an IP address. This function blocks until the lease is renewed, or the process times out.
RETURN VALUE

0: OK, lease was not expired, or an IP address lease was acquired with the same IP address as previously obtained. -1: An error occurred, no IP address is available. TCP/IP functionality is thus not available. Usual causes of an error are timeouts because a DHCP or BOOTP server is not available within the timeout specified by the global variable _bootptimeout (default 30 seconds). 1: Lease was re-acquired, however the IP address differs from the one previously obtained. All existing sockets must be re-opened. Normally, DHCP servers are careful to reassign the same IP address previously used by the client, however this is sometimes not possible.
LIBRARY

BOOTP.LIB

Chapter 7: Function Reference

91

dhcp_get_timezone
int dhcp_get_timezone( long *seconds );
DESCRIPTION

This function returns the time zone offset provided by the DHCP server, if any, or uses the fallback time zone defined by the TIMEZONE macro. Note that TIMEZONE is expressed in hours, whereas the return result is in seconds.
PARAMETERS

seconds

Pointer to result longword. If the return value is 0 (OK), then this will be set to the number of seconds offset from Coordinated Universal Time (UTC). The value will be negative for west; positive for east of Greenwich. If the return value is -1, then the result will be set using the hard-coded value from the macro TIMEZONE (converted to seconds by multiplying by 3600), or zero if this macro is not defined.

RETURN VALUE

0: Time zone obtained from DHCP. -1: Time zone not valid, or not yet obtained, or not using DHCP.
LIBRARY

BOOTP.LIB

92

TCP/IP Users Manual

dhcp_release
int dhcp_release( void );
DESCRIPTION

This function relinquishes a lease obtained from a DHCP server. This allows the server to re-use the IP address that was allocated to this target. After calling this function, the global variable for the IP address is set to 0, and it is not possible to call any other TCP/IP function which requires a valid IP address. Normally, dhcp_release() would be used on networks where only a small number of IP addresses are available, but there are a large number of hosts which need sporadic network access. This function is non-blocking since it only sends one packet to the DHCP server and expects no response.
RETURN VALUE

0: OK, lease was relinquished. 1: Not released, because an address is currently being acquired, or because a boot file (from the BOOTP or DHCP server) is being downloaded, or because some other network resource is in use e.g., open TCP socket. Call dhcp_release() again after the resource is freed. -1: Not released, because DHCP was not used to obtain a lease, or no lease was acquired.
LIBRARY

BOOTP.LIB

Chapter 7: Function Reference

93

getdomainname
char *getdomainname( char *name, int length );
DESCRIPTION

Gets the current domain name. For example, if the controllers internet address is test.mynetwork.com then mynetwork is the domain portion of the name. The domain name can be changed by the setdomainname() function.
PARAMETERS

name length

Buffer to place the name. Maximum length of the name, or zero to get a pointer to the internal domain name string. Do not modify this string!

RETURN VALUE

If length 1: Pointer to name. If length is not long enough to hold the domain name, a NULL string is written to name. If length = 0: Pointer to internal string containing the domain name. Do not modify this string!
LIBRARY

BSDNAME.LIB
SEE ALSO

setdomainname, gethostname, sethostname, getpeername, getsockname


EXAMPLE

main() { sock_init(); printf("Using %s for a domain\n", getdomainname(NULL, 0)); }

94

TCP/IP Users Manual

gethostid
longword gethostid( void );
DESCRIPTION

Return the IP address of the controller in host format.


RETURN VALUE

IP address in host format, or zero if not assigned or not valid.


LIBRARY

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sethostid
EXAMPLE

main() { char buffer[ 512 ]; sock_init(); printf("My IP address is %s\n", inet_ntoa( buffer, gethostid())); }

Chapter 7: Function Reference

95

gethostname
char *gethostname( char *name, int length );
DESCRIPTION

Gets the host portion of our name. For example if the controllers internet address is test.mynetwork.com the host portion of the name would be test. The host name can be changed by the sethostname() function.
PARAMETERS

name length

Buffer to place the name. Maximum length of the name, or zero for the internal host name buffer. Do not modify this buffer.

RETURN VALUE

length 1: Return name. length = 0: Return internal host name buffer (do not modify!).
LIBRARY

BSDNAME.LIB

96

TCP/IP Users Manual

getpeername
int getpeername( sock_type *s, void *dest, int *len );
DESCRIPTION

Gets the peer's IP address and port information for the specified socket.
PARAMETERS

s dest

Pointer to the socket. Pointer to sockaddr to hold the socket information for the remote end of the socket. The data structure is: typedef struct sockaddr { word s_type; // reserved word s_port; // port #, or 0 if not connected longword s_ip; // IP addr, or 0 if not connected byte s_spares[6]; // not used for tcp/ip connections };

len

Pointer to the length of sockaddr. A NULL pointer can be used to represent the sizeof(struct sockaddr).

RETURN VALUE

0: Success. -1: Failure.


LIBRARY

BSDNAME.LIB
SEE ALSO

getsockname

Chapter 7: Function Reference

97

getsockname
int getsockname( sock_type *s, void *dest, int *len );
DESCRIPTION

Gets the controllers IP address and port information for a particular socket.
PARAMETERS

Pointer to the socket. Pointer to sockaddr to hold the socket information for the local end of the socket. The data structure is: typedef struct sockaddr { word s_type; // reserved word s_port; // port #, or 0 if not connected longword s_ip; // IP addr, or 0 if not connected byte s_spares[6]; // not used for tcp/ip connections };

dest

len

Pointer to the length of sockaddr. A NULL pointer can be used to represent the sizeof(struct sockaddr). BSDNAME.LIB will assume 14 bytes if a NULL pointer is passed.

RETURN VALUE

0: Success. -1: Failure.


LIBRARY

BSDNAME.LIB
SEE ALSO

getpeername

98

TCP/IP Users Manual

htonl
longword htonl( longword value );
DESCRIPTION

This function converts a host-ordered double word to a network-ordered double word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network-byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order.
PARAMETERS

value
RETURN VALUE

Host-ordered double word.

Host word in network format, e.g., htonl(0x44332211) returns 0x11223344.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

htons, ntohl, ntohs

Chapter 7: Function Reference

99

htons
word htons( word value );
DESCRIPTION

Converts host-ordered word to a network-ordered word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network-byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order within each 16-bit section.
PARAMETERS

value
RETURN VALUE

Host-ordered word.

Host-ordered word in network-ordered format, e.g., htons(0x1122) returns 0x2211.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

htonl, ntohl, ntohs

100

TCP/IP Users Manual

ifconfig
int ifconfig( int iface,... );
DESCRIPTION

This function replaces tcp_config() for setting network parameters at runtime. In addition, it allows retrieval of parameters and supports multiple interfaces. An arbitrary number of parameters may be set or retrieved in one call. Example: ifconfig( IF_ETH0, IFS_DOWN, IFS_IPADDR, aton("10.10.6.100"), IFS_NETMASK, 0xFFFFFF00uL, IFS_ROUTER_SET, aton("10.10.6.1"), IFS_NAMESERVER_SET, aton("192.68.1.123"), IFS_NAMESERVER_ADD, aton("192.68.1.124"), IFS_UP, IFS_END); This first brings the first Ethernet interface down if it is not already inactive, then it configures the home IP address, netmask, router (gateway), and two nameservers. Finally, the interface is made active (IFS_UP). IFS_END is required to terminate the parameter list.
PARAMETERS

iface

Interface number. Use one of the definitions:

IF_ETH0 IF_ETH1 IF_PPPOE0 IF_PPPOE1 IF_PPPX (X = 0|1|2|3|4|5) IF_ANY

If the interface does not exist, then you will get a compile time error. IF_ANY may be used only for the parameters which are not specific to any particular interface. It can also be used, where applicable, to mean "all interfaces" if the operation would make sense when applied to all interfaces. ... Parameters 2 through n are polymorphic (like printf() parameters). Parameters are provided in groups (usually pairs) with the first parm in the group being one of a documented set of identifiers, and subsequent parms in the group being the value specific to that identifier. The list of parm groups MUST be terminated using the identifier IFS_END. The parameter identifiers are:
101

Chapter 7: Function Reference

Table 4. Parameter Identifiers for ifconfig() Macro Name Macro Description Data Type(s) for Macro Parms

IFS_END IFS_IPADDRa IFG_IPADDR IFS_NETMASK IFG_NETMASK IFS_MTU IFG_MTU IFS_UP IFS_DOWN IFS_HWAa IFG_HWA IFS_NAMESERVER_SETb IFS_NAMESERVER_ADDb

Marks the end of the parameter list. Set IP address. Get IP address. Set netmask. Get netmask. Set maximum transmission unit (MTU). Get MTU. Bring up interface. Bring down interface Set the hardware address. Get the hardware address. Delete all nameservers, then set this one. Add nameserver.

none longword longword * longword longword * word word * none none byte[6] byte[6] longword longword

IFS_ICMP_CONFIG

Use "arp -s" ping to configure IP address, or not. If DHCP and ping configure are both set, then the completion of DHCP will automatically turn off ping configure. If DHCP fails, then ping configure will be allowed after the set int time-out for DHCP. Ping config cannot override DHCP until DHCP has timed out. This is the case whenever a DHCP lease is obtained whether or not at sock_init() time. This parameter may be set for IF_ANY i.e., all interfaces. Get whether or not ping configure is allowed. int * After ping configured okay, allow new ping configure. Get whether ping configured okay. Delete all routers, then set this one. none int * longword

IFG_ICMP_CONFIG IFS_ICMP_CONFIG_RESET IFG_ICMP_CONFIG_OK IFS_ROUTER_SETb

102

TCP/IP Users Manual

Table 4. Parameter Identifiers for ifconfig() Macro Name Macro Description Data Type(s) for Macro Parms

IFS_ROUTER_SET_STATICb,c IFS_DEBUGb IFG_DEBUGb IFS_RESTOREb,d IFG_SAVEb IFS_ROUTER_ADDb


b,c

Set restricted router. Set debug level. Get debug level. Set network interfaces according to saved configuration. Get current network configuration. Add router. Add restricted router.

longword, longword, longword int int * NetConfSave * NetConfSave * longword longword, longword, longword

IFS_ROUTER_ADD_STATIC

IFS_ROUTER_DELb

Delete router If macro parameter = 0, delete longword all routers. Get default router. The interface parameter may be either a specific interface number (to get the default router for that interface), or IF_ANY which will retrieve an overall default router.

IFG_ROUTER_DEFAULT

longword *

IFS_DHCPe IFG_DHCPe IFG_DHCP_OKe IFS_DHCP_TIMEOUTe IFG_DHCP_TIMEOUTe IFS_DHCP_FALLBACKe IFG_DHCP_FALLBACKe IFS_PPP_ACCEPTIP IFG_PPP_ACCEPTIP IFS_PPP_REMOTEIP IFG_PPP_REMOTEIP

Use DHCP to configure this interface, or not. bool Get whether DHCP to be used. bool *

Get whether DHCP actually configured okay. bool * Set DHCP time-out seconds. Get DHCP time-out seconds. Set whether DHCP allows fallback to static configuration. Get whether DHCP allows fallback to static configuration. Accept peer's idea of our local IP address. Get peers idea of our local IP address. Try to set peer's IP address. Get peers IP address. int int * bool bool * bool bool * longword longword *

Chapter 7: Function Reference

103

Table 4. Parameter Identifiers for ifconfig() Macro Name Macro Description Data Type(s) for Macro Parms

IFS_PPP_SETREMOTEIP IFS_PPP_ACCEPTDNS IFG_PPP_ACCEPTDNS

Try to set peer's IP address. Accept a DNS server IP address from peer. Find out if we are accepting a DNS server IP address from peer. Set DNS server IP addresses (primary, secondary) for peer . Get DNS server IP addresses (primary, secondary) for peer. Set DNS server IP address for peer (primary, secondary). Called when a peer attempts to authenticate. The authentication callback is invoked with the following parameters:

longword bool bool * longword, longword longword *, longword * longword, longword

IFS_PPP_REMOTEDNS

IFG_PPP_REMOTEDNS

IFS_PPP_SETREMOTEDNS

IFS_PPP_AUTHCALLBACK

int auth_cb(char *user, int userlen, char *passwd, int passwdlen)

int (*)()

The parameters indicate userid, password and their lengths (not NULL terminated). The callback should return 1 if OK, 0 if not authorized.
IFS_PPP_INIT IFS_PPP_REMOTEAUTH IFG_PPP_REMOTEAUTH

Sets up PPP with default parameters. Sets username and password to give to peer. Gets username and password to give to peer. Required username and password for incoming peer. Get username and password required for incoming peer. Define the RTS pin. Get the definition for the RTS pin. Define the CTS pin. Get the definition for the CTS pin. Turn hardware flow control on/off (1/0).

none char *, char * char **, char ** char *, char * char **, char ** int, char *, int int *, char **, int * int, int int *, int * bool

IFS_PPP_LOCALAUTH

IFG_PPP_LOCALAUTH IFS_PPP_RTSPINf IFG_PPP_RTSPIN IFS_PPP_CTSPINf IFG_PPP_CTSPIN IFS_PPP_FLOWCONTROL

104

TCP/IP Users Manual

Table 4. Parameter Identifiers for ifconfig() Macro Name Macro Description Data Type(s) for Macro Parms

IFG_PPP_FLOWCONTROL IFS_PPP_SPEED IFG_PPP_SPEED

Determine if hardware flow control is on (1) or off (0). Set serial PPP speed in bits/sec. Get serial PPP speed in bits/sec. A series of strings to send and then expect, each separated by a carriage return('\r'). Setting send/expect automatically turns on IF_PPP_USEMODEM. Get the series of strings to send and then expect, each separated by '\r.' Specify whether or not to use modem dialout string.

bool * longword longword *

IFS_PPP_SENDEXPECT

char *

IFG_PPP_SENDEXPECT

char ** bool

IFS_PPP_USEMODEM

IFG_PPP_USEMODEM

Determine whether modem dialout string may bool * be used. Specify whether or not to add the escape sequence <delay>+++<delay> before sending bool send/expect or hangup strings. Determine whether or not the escape sequence <delay>+++<delay> is added before sending bool * send/expect or hangup strings. Use parallel port D instead of parallel port C for serial ports A and B. Determine if parallel port D is being used. Get the PPP peer address. Returns 0 if no connection. bool bool * longword *

IFS_PPP_MODEMESCAPE

IFG_PPP_MODEMESCAPE

IFS_PPP_USEPORTD IFG_PPP_USEPORTD IFG_PPP_PEERADDR

IFS_PPP_HANGUP

Set optional string to send to modem to shut it char * down. Get optional string to send to modem to shut it char ** down.

IFG_PPP_HANGUP

Chapter 7: Function Reference

105

Table 4. Parameter Identifiers for ifconfig() Macro Name Macro Description Data Type(s) for Macro Parms

IFS_IF_CALLBACK

Set interface up/down callback. The interface up/down callback function is called with two parameters: ifcallback(int iface, int up) where iface is the interface number, and up is non-zero if the interface has just come up, or zero if it has just come down. You must #define USE_IF_CALLBACK before #use "dcrtcp.lib" to use this functionality.

void (*)()

a. Setting the value of these parameters may require the interface(s) to be brought down temporarily. If this is necessary it will be brought up again before return, however any sockets that were open on that interface will have been aborted. b. These parameters do not care about the value of iface because they are not specific to an interface. c. "Static router" means a router that handles routing to a specified subnet destination. When a router is selected for a given IP address, the most specific static router will be used. For example, given the following setup: Router 10.10.6.1 10.10.6.2 10.10.6.3 Subnet Mask 0 0 10.99.0.0 255.255.0.0 10.99.57.0 255.255.255.0

then, given a destination IP address (which is not on the local subnet 10.10.6.0), the router will be selected according to the following algorithm: if address is 10.99.57.*, use 10.10.6.3 else if address is 10.99.*.*, use 10.10.6.2 else use 10.10.6.1 Note that IFS_ROUTER_SET is basically the same as IFS_ROUTER_SET_STATIC, except that the subnet and mask parameters are automatically set to zero. Most simple networks with a single router to non-local subnets will use a single IFS_ROUTER_SET. d. The saved configuration does not remember whether the interface is currently active. When restored, all interfaces are set to the inactive state. This facility is intended to allow saving network configuration to non-volatile storage, such as the User block. When restoring a configuration, all interfaces are brought down prior to restoral. e. The DHCP parameters are only available if USE_DHCP is defined, and will only work if the interface parameter is IF_DEFAULT, since DHCP can only be used on the default interface. The IFS_DHCP parameter will cause acquisition or release of the default interface.

106

TCP/IP Users Manual

f. The parameters for the RTS/CTS pin assignments are: RTS: int port_address, char *shadow_reg, int port_pin CTS: int port_address, int port_pin where port_address is the parallel port internal I/O address e.g., PEDR for port E. shadow_reg is the appropriate shadow register for the parallel port data register e.g., &PEDRShadow for port E. port_pin is a number from 0-7 indicating the pin number of the port.
RETURN VALUE

0: Success. >0: identifer of first parameter group that encountered an error. -1: iface parameter is invalid. An exception (run-time error) is raised if the parameter list contains an invalid parameter number.
LIBRARY

NET.LIB
SEE ALSO

sock_init, tcp_config, ip_print_ifs, ifstatus, ifpending

Chapter 7: Function Reference

107

ifdown
int ifdown( int iface );
DESCRIPTION

This function attempts to deactivate the specified interface.


PARAMETER

iface

Interface number. Use one of the definitions

IF_ETH0 IF_ETH1 IF_PPPOE0 IF_PPPOE1 IF_PPPX (X = 0|1|2|3|4|5)

If the interface does not exist, then you will get a compile time error.
RETURN VALUE

IFCTL_OK: if OK. IFCTL_FAIL: if error. IFCTL_PEND: if OK but not complete.


LIBRARY

NET.LIB
SEE ALSO

ifconfig, ifup, ifstatus, ifpending

108

TCP/IP Users Manual

ifpending
int ifpending( int iface );
DESCRIPTION

Returns indication of whether the specified interface is up, down, pending up or pending down. This reveals more information than ifstatus(), which only indicates the current state (up or down).
NOTE: ANDing the return value with 0x01 indicates a pending condition; ANDing with 0x02 is equivalent to the return from ifstatus().
PARAMETERS

iface

Interface number. Use one of the definitions:

IF_ETH0 IF_ETH1 IF_PPPOE0 IF_PPPOE1 IF_PPPX (X = 0|1|2|3|4|5)

If the interface does not exist, you will get a compile time error.
RETURN VALUE

0: If interface is currently down and not pending up. 1: If interface is currently down and pending up. 2: If interface is currently up and not pending down. 3: If interface is currently up and pending down.
LIBRARY

NET.LIB
SEE ALSO

ifconfig, ifdown, ifup, ifstatus

Chapter 7: Function Reference

109

ifstatus
int ifstatus( int iface );
DESCRIPTION

This macro returns the status of the specified interface.


PARAMETER

iface

Interface number. Use one of the definitions

IF_ETH0 IF_ETH1 IF_PPPOE0 IF_PPPOE1 IF_PPPX (X = 0|1|2|3|4|5)

If the interface does not exist, then you will get a compile time error.
RETURN VALUE

0: if interface is currently down. Non-zero if interface is currently up (active).


LIBRARY

NET.LIB
SEE ALSO

ifconfig, ifup, ifdown, ifpending

110

TCP/IP Users Manual

ifup
int ifup( int iface );
DESCRIPTION

This function attempts to activate the specified interface.


PARAMETER

iface

Interface number. Use one of the definitions

IF_ETH0 IF_ETH1 IF_PPPOE0 IF_PPPOE1 IF_PPPX (X = 0|1|2|3|4|5)

If the interface does not exist, then you will get a compile time error.
RETURN VALUE

IFCTL_OK: if OK. IFCTL_FAIL: if error. IFCTL_PEND: if OK but not complete.


LIBRARY

NET.LIB
SEE ALSO

ifconfig, ifdown, ifstatus

Chapter 7: Function Reference

111

inet_addr
longword inet_addr( char *dotted_ip_string );
DESCRIPTION

Converts an IP address from dotted decimal IP format to its binary representation. No check is made as to the validity of the address.
PARAMETERS

dotted_ip_string
RETURN VALUE

Dotted decimal IP string, e.g., "10.10.6.100".

0: Failure. Binary representation of dotted_ip_string: Success.


LIBRARY

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

inet_ntoa

112

TCP/IP Users Manual

inet_ntoa
char *inet_ntoa( char *s, longword ip );
DESCRIPTION

Converts a binary IP address to its dotted decimal format, e.g., inet_ntoa(s,0x0a0a0664) returns a pointer to "10.10.6.100".
PARAMETERS

Location to place the dotted decimal string. A sufficient buffer size would be 16 bytes. The IP address to convert.

ip
RETURN VALUE

Pointer to the dotted decimal string pointed to by s.


LIBRARY

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

inet_addr

Chapter 7: Function Reference

113

ip_iface
byte ip_iface( longword ipaddr, int local_only );
DESCRIPTION

Given an IP address, this function return the interface number for that address. If ipaddr is an address on one of the local subnets, then the interface to that subnet is returned. If the address is not local, then the local_only parameter determines the result: If local_only is 1, then IF_ANY will be returned for a non-local address. Otherwise, the router_for() function is invoked to find the correct router -- the interface for the router is returned.
PARAMETERS

ipaddr local_only

IP address of an external host. 0: allow non-local addresses (returns interface for router). 1: return IF_ANY for non-local addresses.

RETURN VALUE

Interface number (0..IF_MAX-1), of possibly IF_ANY (0xFF).


LIBRARY

IP.LIB
SEE ALSO

router_for

114

TCP/IP Users Manual

ip_print_ifs
void ip_print_ifs( void );
DESCRIPTION

Print all interface table entries. This is for debugging only, since the results are printed to the Dynamic C Stdio window. There are 8 fields for each interface entry: # IP addr The interface number The local ("home") IP address of this interface. May be 0.0.0.0 if interface is not currently active. Local subnet mask. Indicates status; one of Yes: interface currently active No: currently inactive NYU: Not Yet Up i.e., coming up NYD: Not Yet Down i.e., coming down Type: Interface type; one of eth: normal Ethernet ppp: PPP over serial port pppoe: PPP over Ethernet MTU: Flags: Maximum transmission unit. A list of the following characters: *: this is the default interface (IF_DEFAULT) D: Use DHCP DD: Currently configured via DHCP S: allow IP addr configuration via directed ping (ICMP echo). SS: IP address currently set via directed ping 1: IGMP version 1 router present on this interface Peer/router IP address of peer node (for PPP or PPPoE), or address of default router on this interface (for Ethernet type). May be blank or 0.0.0.0 if no peer or router is available.

Mask Up

LIBRARY

IP.LIB

Chapter 7: Function Reference

115

ip_timer_expired
word ip_timer_expired( void *s );
DESCRIPTION

Check the timer inside the socket structure that was set by ip_timer_init().
PARAMETER

s
RETURN VALUE

Pointer to a socket.

0: If not expired. 1: If expired.


LIBRARY

NET.LIB
SEE ALSO

ip_timer_init

116

TCP/IP Users Manual

ip_timer_init
void ip_timer_init( void *s, word seconds );
DESCRIPTION

Set a timer inside the socket structure.


PARAMETER

s seconds

Pointer to a socket. Number of seconds for the time-out; if seconds is zero never time-out.

RETURN VALUE

None.
LIBRARY

NET.LIB
SEE ALSO

ip_timer_expired

Chapter 7: Function Reference

117

is_valid_iface
int is_valid_iface( int iface );
DESCRIPTION

This function returns a boolean indicator of whether the given interface number is valid for the configuration.
PARAMETER

iface

Interface number. Use one of the definitions


RETURN VALUE

IF_ETH0 IF_ETH1 IF_PPPOE0 IF_PPPOE1 IF_PPPX (X = 0|1|2|3|4|5)

!0: Interface is valid. 0: Interface does not exist.


LIBRARY

NET.LIB
SEE ALSO

ifconfig, ifup, ifdown, ifstatus

118

TCP/IP Users Manual

multicast_joingroup
int multicast_joingroup( int iface, longword ipaddr );
DESCRIPTION

This function joins the specified multicast group (class D IP address--from 224.0.0.0 to 239.255.255.255) on the specified interface. For an Ethernet interface, it configures the hardware to accept multicast packets for the specified address. Note that this function is called automatically when udp_open() is used to open a multicast address.
PARAMETER

iface

Interface on which to join the group. Use one of the definitions

IF_ETH0 IF_ETH1 IF_DEFAULT


ipaddr
RETURN VALUE

Multicast group to join.

0: Success. 1: Failure (e.g., ipaddr is not a multicast address; or not enough available ARP entries to hold the group).
LIBRARY

IGMP.LIB

Chapter 7: Function Reference

119

multicast_leavegroup
int multicast_leavegroup( int iface, longword ipaddr );
DESCRIPTION

This function leaves the specified multicast group (class D IP address--from 224.0.0.0 to 239.255.255.255) on the specified interface. For an Ethernet interface, it configures the hardware to no longer accept multicast packets for the specified address. This function will leave the group no matter how many multicast_joingroup() calls were made on that group. However, note that this function will not actually leave a group for which there are UDP sockets. However, when those UDP sockets close, the group will be left. Note that this function is called automatically when a multicast UDP socket is closed.
PARAMETER

iface

Interface on which to leave the group. Use one of the definitions

IF_ETH0 IF_ETH1 IF_DEFAULT


ipaddr
RETURN VALUE

Multicast group to leave.

0: Success. 1: Failure (e.g., ipaddr is not a multicast address).


LIBRARY

IGMP.LIB

120

TCP/IP Users Manual

ntohl
longword ntohl( longword value );
DESCRIPTION

Converts network-ordered long word to host-ordered long word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order.
PARAMETERS

value
RETURN VALUE

Network-ordered long word.

Network-ordered long word in host-ordered format, e.g., ntohl(0x44332211) returns 0x11223344


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

htons, ntohs, htonl

Chapter 7: Function Reference

121

ntohs
word ntohs( word value );
DESCRIPTION

Converts network-ordered word to host-ordered word. This function is necessary if you are implementing standard internet protocols because the Rabbit does not use the standard for network byte ordering. The network orders bytes with the most significant byte first and the least significant byte last. On the Rabbit, the bytes are in the opposite order.
PARAMETERS

value
RETURN VALUE

Network-ordered word.

Network-ordered word in host-ordered format, e.g., ntohs(0x2211) returns 0x1122


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

htonl, ntohl, htons

122

TCP/IP Users Manual

paddr
unsigned long paddr( void *pointer );
DESCRIPTION

Converts a logical pointer into its physical address. Use caution when converting address in the E000-FFFF range. This function will return the address based on the XPC on entry.
PARAMETERS

pointer
RETURN VALUE

Pointer to convert.

Physical address of pointer.


LIBRARY

XMEM.LIB

Chapter 7: Function Reference

123

pd_getaddress
void pd_getaddress( int nic, void *buffer );
DESCRIPTION

This function copies the Ethernet address (aka the MAC address) into the buffer.
PARAMETERS

nic

Starting with Dynamic C 7.30, this parameter identifies an Ethernet interface. Use a value of 0 if only one NIC is present Place to copy address to. Must be at least 6 byes.

buffer
RETURN VALUE

None.
LIBRARY

PKTDRV.LIB
EXAMPLE

main() { char buf[6]; sock_init(); pd_getaddress(0,buf); printf("Your Link Address is:%02x%02x:%02x%02x:%02x%02x \n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]); }

124

TCP/IP Users Manual

pd_havelink
int pd_havelink( int nic );
DESCRIPTION

Determines if the physical-layer link is established for the specified NIC.


PARAMETERS

nic
RETURN VALUE

The NIC to check. Use a value of 0 if only one NIC is present.

0: There is no link. !0: The link is established.


LIBRARY

REALTEK.LIB | ASIX.LIB | SMSC.LIB

Chapter 7: Function Reference

125

pd_powerdown
int pd_powerdown( int nic );
DESCRIPTION

Power down the NIC, by turning off as many services as possible. When the NIC is in powerdown mode, it is very important to not call any TCP/IP, ethernet, etc. functions, as they will obviously fail, and the results will be undefined. pd_powerup() should be the very next network function called, to re-enable the NIC.
PARAMETERS

nic

The NIC to powerdown. Use a value of 0 if only one NIC is present.

RETURN VALUE

0: Success. !0: Error.


LIBRARY

REALTEK.LIB | ASIX.LIB | SMSC.LIB


SEE ALSO

pd_powerup

126

TCP/IP Users Manual

pd_powerup
int pd_powerup( int nic );
DESCRIPTION

Power up the NIC, undoing the sleepy-mode changes made by pd_powerdown. After this function has returned success, Ethernet and TCP/IP function may be called again.
NOTE: This function will block for 10 ms, to let the chip start up.
PARAMETERS

nic
RETURN VALUE

The NIC to power up. Use a value of 0 if only one NIC is present.

0: Success. !0: Error.


LIBRARY

REALTEK.LIB | ASIX.LIB | SMSC.LIB


SEE ALSO

pd_powerdown

Chapter 7: Function Reference

127

_ping
int _ping( longword host_ip, longword sequence_number );
DESCRIPTION

Generates an ICMP request for host. NOTE: this is a macro that calls _send_ping.
PARAMETERS

host_ip sequence_number
RETURN VALUE

IP address to send ping. User-defined sequence number.

0: Success. 1: Failure, unable to resolve hardware address. -1: Failure, unable to transmit ICMP request.
LIBRARY

ICMP.LIB
SEE ALSO

_chk_ping, _send_ping

128

TCP/IP Users Manual

psocket
void psocket( void *s );
DESCRIPTION

Given an open UDP or TCP socket, the IP address of the remote host is printed out to the Stdio window in dotted IP format followed by a colon and the decimal port number on that machine. This routine can be useful for debugging your programs.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

None.
LIBRARY

BSDNAME.LIB

Chapter 7: Function Reference

129

resolve
longword resolve( char *host_string );
DESCRIPTION

Converts a text string, which contains either the dotted IP address or host name, into the longword containing the IP address. In the case of dotted IP, no validity check is made for the address. NOTE: this function blocks. Names are currently limited to 64 characters. If it is necessary to lookup larger names include the following line in the application program: #define DNS_MAX_NAME <len in chars> If DISABLE_DNS has been defined, resolve() will not do DNS lookup. If you are trying to resolve a host name, you must set up at least one name server. You can set the default name server by defining the MY_NAMESERVER macro at the top of your program. When you call resolve(), it will contact the name server and request the IP address. If there is an error, resolve() will return 0L. To simply convert dotted IP to longword, see inet_addr(). For a sample program, see the Example Using tcp_open() listed under tcp_open().
PARAMETERS

host_string
RETURN VALUE

Pointer to text string to convert.

0: Failure. !0: The IP address *host_string resolves to.


LIBRARY

DNS.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

_arp_resolve, inet_addr, inet_ntoa

130

TCP/IP Users Manual

resolve_cancel
int resolve_cancel( int handle );
DESCRIPTION

Cancels the resolve request represented by the given handle. If the handle is 0, then this function cancels all outstanding resolve requests.
PARAMETERS

handle

Handle that represents a DNS lookup process, or 0 to cancel all outstanding resolve requests.

RETURN VALUE

RESOLVE_SUCCESS: The resolve request has been cancelled and is no longer valid. RESOLVE_HANDLENOTVALID: There is no request for the given handle. RESOLVE_NONAMESERVER: No nameserver has been defined.
LIBRARY

DNS.LIB
SEE ALSO

resolve_name_start, resolve_name_check, resolve

Chapter 7: Function Reference

131

resolve_name_check
int resolve_name_check( int handle, longword *resolved_ip );
DESCRIPTION

Checks if the DNS lookup represented by the given handle has completed. On success, it fills in the resolved IP address in the space pointed to by resolved_ip.
PARAMETERS

handle resolved_ip

Handle that represents a DNS lookup process. A pointer to a user-supplied longword where the resolved IP address will be placed.

RETURN VALUE

RESOLVE_SUCCESS: The address was resolved. The given handle will no longer be valid after this value is returned. RESOLVE_AGAIN: The resolve process has not completed, call this function again. RESOLVE_FAILED: The DNS server responded that the given host name does not exist. The given handle will no longer be valid if RESOLVE_FAILED is returned. RESOLVE_TIMEDOUT: The request has been cancelled because a response from the DNS server was not received before the last time-out expired. The given handle will no longer be valid after this value is returned. RESOLVE_HANDLENOTVALID: There is no DNS lookup occurring for the given handle. RESOLVE_NONAMESERVER: No nameserver has been defined.
LIBRARY

DNS.LIB
SEE ALSO

resolve_name_start, resolve_cancel, resolve

132

TCP/IP Users Manual

resolve_name_start
int resolve_name_start( char *hostname );
DESCRIPTION

Starts the process of resolving a host name into an IP address. The given host name is limited to DNS_MAX_NAME characters, which is 64 by default (63 characters + the NULL terminator). If a default domain is to be added, then the two strings together are limited to DNS_MAX_NAME. If hostname does not contain a '.' then the default domain (MY_DOMAIN) , if provided, is appended to hostname. If hostname with the appended default domain does not exist, hostname is tried by itself. If that also fails, the lookup fails. If hostname does contain a '.' then hostname is looked up by itself. If it does not exist, the default domain is appended, and that combination is tried. If that also fails, the lookup fails. If hostname ends with a '.', then the default domain is not appended. The host name is considered fully qualified. The lookup is attempted without the ending '.' and if that fails no other combinations are attempted. This function returns a handle that must be used in the subsequent resolve_name_check() and resolve_cancel() functions.
PARAMETERS

hostname
RETURN VALUE

Host name to convert to an IP address

>0: Handle for calls to resolve_name_check() and resolve_cancel(). RESOLVE_NOENTRIES: Could not start the resolve process because there were no resolve entries free. RESOLVE_LONGHOSTNAME: The given hostname was too large. RESOLVE_NONAMESERVER: No nameserver has been defined.
LIBRARY

DNS.LIB
SEE ALSO

resolve_name_check, resolve_cancel, resolve

Chapter 7: Function Reference

133

rip
char *rip( char *string );
DESCRIPTION

Strips newline (\n) and/or carriage return (\r) from a string. Only the first \n and \r characters are replaced with \0s. The resulting string beyond the first \0 character is undefined.
PARAMETERS

string
RETURN VALUE

Pointer to a string.

Pointer to the modified string.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


EXAMPLE

setmode( s, TCP_MODE_ASCII ); ... sock_puts( s, rip( questionable_string ));


NOTE: In ASCII mode sock_puts() adds \n; rip is used to make certain the string does not already have a newline character. Remember, rip modifies the source string, not a copy!

134

TCP/IP Users Manual

router_add
ATHandle router_add( longword ipaddr, byte iface, longword subnet, longword mask, word flags );
DESCRIPTION

Add a router to the router table. The same router can be added multiple times, with different subnet and mask. Normally, only one entry is needed in order to access non-local subnets: this entry should be specified with a zero mask. The hardware address of the router is not immediately resolved, however this can be done explicitly by calling arpresolve_start() with the same IP address. Otherwise, the router will be resolved only when it first becomes necessary.
PARAMETERS

ipaddr

IP address of the router. This address should be on the local subnet, since non-local routers are not supported. Interface to use to access this router, or IF_DEFAULT. Subnet accessible through this entry. Subnet mask for this entry. Flags word: set to zero (non-zero reserved for internal use).

iface subnet mask flags


RETURN VALUE

Positive value: completed successfully. The return value is the ARP cache table entry for this router. ATH_NOENTRIES: insufficient space in either the router or ARP cache tables.
LIBRARY

ARP.LIB

router_del_all
void router_del_all( void );
DESCRIPTION

Delete all router table entries. This will make any host that is not on the local subnet inaccessible. This function is usually called in preparation for adding a new router entry.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

135

router_delete
ATHandle router_delete( longword ipaddr );
DESCRIPTION

Delete a router from the router table. All instances of the router's IP address are deleted, and the ARP cache table entry is flushed.
PARAMETER

ipaddr

IP address of the router. This address should be on the local subnet, since non-local routers are not supported.

RETURN VALUE

Positive value: completed successfully. ATH_NOTFOUND: specified entry did not exist.
LIBRARY

ARP.LIB

136

TCP/IP Users Manual

router_for
ATHandle router_for( longword ipaddr, byte *router_used, byte *r_iface );
DESCRIPTION

Return the ARP cache table entry corresponding to the router that handles the given IP address. If there is a pre configured router for the given address, it is selected. Otherwise, routers discovered via DHCP or ICMP router discovery are searched, with the highest preference being selected. Failing this, if there is a point-to-point interface, this is selected as the default. An alternative mode of calling this function is invoked if ipaddr is zero. In this case, the default router for the specified interface (*r_iface) is returned. If r_iface is NULL, then the default interface is assumed:IF_DEFAULT, the only interface supported at present. IF_DEFAULT may refer to the primary Ethernet NIC or a PPP connection that uses a serial port or the primary Ethernet NIC.
PARAMETERS

ipaddr router_used

IP address of the host which is not on the local subnet. If not NULL, the byte at this location is set to the index of the router in the router table. If not NULL, the byte at this location is set to the interface number that can access the router.

r_iface

RETURN VALUE

Positive value: completed successfully. ATH_NOROUTER: no suitable router found. Either no router is configured, or the given IP address is on the local subnet.
LIBRARY

ARP.LIB

Chapter 7: Function Reference

137

router_print
int router_print( byte r );
DESCRIPTION

Print a router table entry, indexed by 'r.' This is for debugging only, since the results are printed to the Dynamic C stdio window. 'r' may be obtained from the router_for() function, by passing &r as the router_used parameter to that function. If the specified router entry is not in use, nothing is printed and the return value is nonzero. Otherwise, the information is printed and zero returned. See router_printall() for a description of the output fields printed.
PARAMETER

Router table index. A number from 0 through (ARP_ROUTER_TABLE_SIZE-1).

RETURN VALUE

0: Success, information printed to stdio window. !0: Entry is not in use.


LIBRARY

ARP.LIB
SEE ALSO

router_printall

138

TCP/IP Users Manual

router_printall
int router_printall( void );
DESCRIPTION

Print all router table entries. This is for debugging only, since the results are printed to the Dynamic C stdio window. If no routers exist in the table, nothing is printed and the return value is non-zero. There are 6 fields for each router entry:

Router Table Entry Field

Description of Field

The entry number. A list of the following characters: P = this entry pre configured T = transient entry D = added by DHCP/BOOTP R = added by ICMP redirect ? = router not reachable H = router's hardware address resolved Either the router's IP address or an indication that the entry is a point-to-point link. Interface number. For pre configured entries, indicates the network(s) which are served by this entry (the Mask indicates which bits of the IP address are used to match with the network address). For nonpre configured entries, this is the "preference value" assigned. For pre configured entries, the bitmask to apply to IP addresses when matching against the above network. Otherwise, is the expiry time from the present, in seconds, of a transient entry.

Flags

Address i/f

Net/preference

Mask/exp(sec)

RETURN VALUE

0: Success, information printed to stdio window. !0: No routers in the table.


LIBRARY

ARP.LIB

Chapter 7: Function Reference

139

_send_ping
int _send_ping( longword host, longword countnum, byte ttl, byte tos, longword *theid );
DESCRIPTION

Generates an ICMP request for host.


PARAMETERS

host countnum ttl

IP address to send ping. User-defined count number. Time to live for the packets (hop count). 255 is a standard value for this field. See sock_set_ttl() for details. Type of service on the packets. See sock_set_tos() for details. The identifier that was sent out.

tos

theid
RETURN VALUE

0: Success. 1: Failure: unable to resolve hardware address. -1: Failure: unable to transmit ICMP request.
LIBRARY

ICMP.LIB
SEE ALSO

_chk_ping, _ping, sock_set_ttl, sock_set_tos

140

TCP/IP Users Manual

setdomainname
char *setdomainname( char *name );
DESCRIPTION

The domain name returned by getdomainname() and used for resolve() is set to the value in the string pointed to by name. Changing the contents of the string after a setdomainname() will change the value of the system domain string. It is not recommended. Instead dedicate a static location for holding the domain name. setdomainname( NULL ) is an acceptable way to remove any domain name and subsequent resolve calls will not attempt to append a domain name.
PARAMETERS

name
RETURN VALUE

Pointer to string.

Pointer to string that was passed in.


LIBRARY

BSDNAME.LIB
SEE ALSO

getdomainname, sethostname, gethostname, getpeername, getsockname

Chapter 7: Function Reference

141

sethostid
longword sethostid( longword ip );
DESCRIPTION

This function changes the systems current IP address. Changing this address will disrupt existing TCP or UDP sessions. You should close all sockets before calling this function. Normally there is no need to call this function. The macro MY_IP_ADDRESS defines an initial IP address for this host, or you can define USE_DHCP to obtain a dynamically assigned address. In either case, it is not recommended to use this function to change the address.
PARAMETERS

ip
RETURN VALUE

New IP address.

New IP address.
LIBRARY

IP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

gethostid

142

TCP/IP Users Manual

sethostname
char *sethostname( char *name );
DESCRIPTION

Sets the host portion of our name.


PARAMETERS

name
RETURN VALUE

The new host name.

Pointer to internal hostname buffer on success. NULL on error (if hostname is too long).
LIBRARY

BSDNAME.LIB

Chapter 7: Function Reference

143

sock_abort
void sock_abort( void *s );
DESCRIPTION

Close a connection immediately. Under TCP this is done by sending a RST (reset). Under UDP there is no difference between sock_close() and sock_abort().
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

None.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_close, tcp_open

144

TCP/IP Users Manual

sock_alive
int sock_alive( tcp_Socket *s );
DESCRIPTION

This function performs the same test as tcp_tick(s) i.e., it checks the status of the socket and returns 0 if the socket is fully closed. The processing overhead of tcp_tick() is avoided for cases where several sockets need to be checked in succession. When this function returns zero for a socket, the socket is then ready for a new call to tcp_open() or tcp_listen() and friends.
PARAMETER

s
RETURN VALUE

TCP socket pointer.

0: Connection reset or fully closed. Socket ready for re-use in another connection. !0: Connection is opening, established, listening, or in the process of closing.
LIBRARY

TCP.LIB
SEE ALSO

tcp_open, tcp_listen, sock_close, sock_abort, tcp_tick

Chapter 7: Function Reference

145

sock_aread
int sock_aread( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

Read exactly len bytes from the socket or, if that amount of data is not yet available, do not read anything. Unlike sock_fastread(), this function will never return less than the requested amount of data. This can be useful when the application knows that it will be receiving a fixed amount of data, but does not wish to handle the arrival of only part of the data, as it would have to do if sock_fastread() was used. len must be less than or equal to the socket receive buffer size, otherwise sock_fastread() must be used. This function is only valid for TCP sockets. It is available starting with DC 7.30.
PARAMETERS

s dp len
RETURN VALUE

Pointer to a TCP socket. Buffer to place bytes that are read. Number of bytes to copy to the buffer.

-1: -2: -3: 0:

len is greater than the total socket receive buffer size, hence this request could never be satisfied in one call. The socket is closed or closing, but insufficient data is in the buffer to satisfy the request. len < 0 or the socket parameter was invalid. Insufficient data is in the buffer to satisfy the request, or len was zero. Try again later since the socket is still able to receive data from the peer. The len parameter is returned if there was sufficient data in the socket buffer to satisfy the request.

len:

LIBRARY

TCP.LIB
SEE ALSO

sock_fastread, sock_xfastread, sock_fastwrite, sock_xfastwrite, sock_axread, sock_awrite, sock_axwrite

146

TCP/IP Users Manual

sock_awrite
int sock_awrite( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

Write exactly len bytes to the socket or, if that amount of data can not be written, do not write anything. Unlike sock_fastwrite(), this function will never return less than the requested amount of data. This can be useful when the application needs to write a fixed amount of data, but does not wish to handle the transmission of only part of the data, as it would have to do if sock_fastwrite() was used. len must be less than or equal to the socket transmit buffer size, otherwise sock_fastwrite() must be used. This function is only valid for TCP sockets. It is available starting with DC 7.30. Parameters s dp len
RETURN VALUE

Pointer to a TCP socket. Buffer containing data to write. Number of bytes to write to the socket buffer.

-1: -2: -3: 0:

len is greater than the total socket receive buffer size, hence this request could never be satisfied in one call. The socket has been closed for further transmissions, e.g., because sock_close() has already been called. len < 0 or the socket parameter was invalid. Insufficient free space in the transmit buffer to satisfy the request, or len was zero. Try again later since the peer will eventually acknowledge the receipt of previous data, freeing up transmit buffer space. The len parameter is returned if there was sufficient data in the socket transmit buffer to satisfy the request.

len:

LIBRARY

TCP.LIB
SEE ALSO

sock_fastread, sock_xfastread, sock_fastwrite, sock_xfastwrite, sock_axread, sock_aread, sock_axwrite

Chapter 7: Function Reference

147

sock_axread
int sock_axread( tcp_Socket *s, long dp, int len );
DESCRIPTION

Reads exactly len bytes from the socket or, if that amount of data is not yet available, do not read anything. This function is available starting with DC 7.30. It is identical to sock_aread() except that the destination buffer is in xmem.
PARAMETERS

s dp len
RETURN VALUE

Pointer to a TCP socket. Buffer to place bytes that are read. Number of bytes to copy to the buffer.

-1: -2: -3: 0:

len is greater than the total socket receive buffer size, hence this request could never be satisfied in one call. The socket is closed or closing, but insufficient data is in the buffer to satisfy the request. len < 0 or the socket parameter was invalid. Insufficient data is in the buffer to satisfy the request, or len was zero. Try again later since the socket is still able to receive data from the peer. The len parameter is returned if there was sufficient data in the socket buffer to satisfy the request.

len:

LIBRARY

TCP.LIB
SEE ALSO

sock_fastread, sock_xfastread, sock_fastwrite, sock_xfastwrite, sock_aread, sock_awrite, sock_axwrite

148

TCP/IP Users Manual

sock_axwrite
int sock_axwrite( tcp_Socket *s, long dp, int len );
DESCRIPTION

Write exactly len bytes to the socket or, if that amount of data can not be written, do not write anything. This function is available starting with DC 7.30. It is identical to sock_awrite() except that the source buffer is in xmem. Parameters s dp len
RETURN VALUE

Pointer to a TCP socket. Buffer containing data to write. Number of bytes to write to the socket buffer.

-1: -2: -3: 0:

len is greater than the total socket receive buffer size, hence this request could never be satisfied in one call. The socket has been closed for further transmissions, e.g., because sock_close() has already been called. len < 0 or the socket parameter was invalid. Insufficient free space in the transmit buffer to satisfy the request, or len was zero. Try again later since the peer will eventually acknowledge the receipt of previous data, freeing up transmit buffer space. the len parameter is returned if there was sufficient data in the socket transmit buffer to satisfy the request.

len:

LIBRARY

TCP.LIB
SEE ALSO

sock_fastread, sock_xfastread, sock_fastwrite, sock_xfastwrite, sock_axread, sock_aread, sock_awrite

Chapter 7: Function Reference

149

sock_bytesready
int sock_bytesready( void *s );
DESCRIPTION

For TCP sockets: If the socket is in binary mode, sock_bytesready() returns the number of bytes waiting to be read. If there are no bytes waiting, it returns -1. In ASCII mode, sock_bytesready() returns -1 if there are no bytes waiting to be read or the line that is waiting is incomplete (no line terminating character has been read). The number of bytes waiting to be read will be returned given one of the following conditions:

the buffer is full the socket has been closed (no line terminating character can be sent) a complete line is waiting
In ASCII mode, a blank line will be read as a complete line with length 0, which will be the value returned. sock_bytesready() handles ASCII mode sockets better than sock_dataready(), since it can distinguish between an empty line on the socket and an empty buffer. For UDP sockets: Returns the number of bytes in the next datagram to be read. If it is a datagram with no data (an empty datagram), then it will return 0. If there are no datagrams waiting, then it returns -1.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

-1: No bytes waiting to be read. 0: If in ASCII mode and a blank line is waiting to be read; for DC 7.05 and later, a UDP datagram with 0 bytes of data is waiting to be read. >0: The number of bytes waiting to be read.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_established, sockstate

150

TCP/IP Users Manual

sock_close
void sock_close( void *s );
DESCRIPTION

Close an open socket. The socket cannot be reused until it is completely closed. In the case of UDP, the socket is closed immediately. TCP, being a connection-oriented protocol, must negotiate the close with the remote computer. You can tell a TCP socket is closed by tcp_tick(s)==NULL or by running sock_wait_closed(s). In emergency cases, it is possible to abort the TCP connection rather than close it. Although not recommended for normal transactions, this service is available and is used by all TCP/IP systems.
PARAMETERS

s
LIBRARY

Pointer to a socket.

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_abort, sock_tick, sock_wait_closed, tcp_open, udp_open

Chapter 7: Function Reference

151

sock_dataready
int sock_dataready( void *s );
DESCRIPTION

Returns the number of bytes waiting to be read. If the socket is in ASCII mode, this function returns zero if a newline character has not been read or the buffer is not full. For UDP sockets, the function returns the number of bytes in the next datagram. This function cannot tell the difference between no bytes to read and either a blank line or a UDP datagram with no data. For this reason, use sock_bytesready() instead.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

0: No bytes to read; or newline not yet read if the socket is in ASCII mode; or (for DC 7.05 and later) if a UDP datagram has 0 bytes of data waiting to be read. >0: Number of bytes ready to read.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_bytesready

152

TCP/IP Users Manual

sockerr
char *sockerr( void *s );
DESCRIPTION

Gets the last ASCII error message recorded for the specified socket. Use of this function will introduce a lot of string constants in root memory. For production programs, it is better to use error numbers (without translation to strings).
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

Pointer to the string that represents the last error message for the socket. NULL pointer if there have been no errors. If the symbol SOCKERR_NO_RETURN_NULL is defined, then if no error occurred the string "OK" will be returned instead of a NULL pointer. The error messages are read-only; do not modify them!
LIBRARY

NETERRNO.LIB
SEE ALSO

sock_error, sock_perror
EXAMPLE

char *p; ... if ( p = sockerr( s )) printf("Socket closed with error '%s'\n\r", p );

Chapter 7: Function Reference

153

sock_error
int sock_error( void *s, int clear );
DESCRIPTION

Return the most recent error number for the specified socket, which may be a TCP or UDP socket. Up to two error codes may be queued to a socket.
PARAMETERS

s clear

socket 0: do not clear the returned error condition. 1: clear the returned error from the socket. You can call this function again to get the next older error code (if any).

RETURN VALUE

0: No error. !0: One of the NETERR_* constants defined in NETERRNO.LIB.


LIBRARY

NETERRNO.LIB
SEE ALSO

sockerr, sock_perror

154

TCP/IP Users Manual

sock_established
int sock_established( void *s );
DESCRIPTION

TCP connections require a handshaked open to ensure that both sides recognize a connection. Whether the connection was initiated with tcp_open() or tcp_listen(), sock_established() will continue to return 0 until the connection is established, at which time it will return 1. It is not enough to spin on this after a listen because it is possible for the socket to be opened, written to and closed between two checks. sock_bytesready() can be called with sock_established() to handle this case. UDP is a connectionless protocol, hence sock_established() always returns 1 for UDP sockets.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

0: Not established. 1: Established.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_bytesready, sockstate

Chapter 7: Function Reference

155

sock_fastread
int sock_fastread( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

Reads up to len bytes from dp on socket s. If possible this function fills the buffer, otherwise only the number of bytes immediately available, if any, are returned. Starting with Dynamic C 7.05, this function is only valid for TCP sockets. For UDP sockets, use udp_recv() or udp_recvfrom(). Prior to 7.05, this function cannot be used on UDP sockets after sock_recv_init() is called.
PARAMETERS

s dp len
RETURN VALUE

Pointer to a socket. Buffer to put bytes that are read. Maximum number of bytes to write to the buffer.

0: Success, number of bytes read. -1: Error.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_read, sock_fastwrite, sock_write, sockerr, udp_recv, udp_recvfrom, sock_xfastwrite, sock_aread, sock_axread


EXAMPLE

Note that sock_fastread() and sock_read() do not necessarily return a complete or single linethey return blocks of bytes. In comparison, sock_getc() returns a single byte at a time and thus yields poor performance.

do { /* this function does not block */ len = sock_fastread( s, buffer, sizeof(buffer)-1 ); if (len>0) { buffer[ len ] = 0; printf( "%s", buffer ); } } while(tcp_tick(s));

156

TCP/IP Users Manual

sock_fastwrite
int sock_fastwrite( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

Writes up to len bytes from dp to socket s. This function writes as many bytes as possible to the socket and returns that number of bytes. Starting with Dynamic C 7.05, this function is only valid for TCP sockets. For UDP sockets, use udp_send() or udp_sendto(). When using a UDP socket prior to DC 7.05, sock_fastwrite() will send one record if len <= ETH_MTU - 20 - 8 ETH_MTU is the Ethernet Maximum Transmission Unit; 20 is the IP header size and 8 is the UDP header size. By default, this is 572 bytes. If len is greater than this number, then the function does not send the data and returns -1. Otherwise, the UDP datagram would need to be fragmented. For TCP, the new data is queued for sending and sock_fastwrite() returns the number of bytes that will be sent. The data may be transmitted immediately if enough data is in the buffer, or sufficient time has expired, or the user has explicitly used sock_flushnext() to indicate this data should be flushed immediately. In either case, no guarantee of acceptance at the other end is possible.
PARAMETERS

s dp len
RETURN VALUE

Pointer to a socket. Buffer to be written. Maximum number of bytes to write to the socket.

0: Success, number of bytes written. -1: Error.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_write, sock_fastread, sock_read, sockerr, sock_flush, sock_flushnext, udp_send, udp_sendto, sock_xfastwrite

Chapter 7: Function Reference

157

sock_flush
void sock_flush( tcp_Socket *s );
DESCRIPTION

sock_flush() will flush the unwritten portion of the TCP buffer to the network. No guarantee is given that the data was actually delivered. In the case of a UDP socket, no action is taken. sock_flushnext() is recommended over sock_flush().
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

None.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_flushnext, sock_fastwrite, sock_write, sockerr

158

TCP/IP Users Manual

sock_flushnext
void sock_flushnext( tcp_Socket *s );
DESCRIPTION

Writing to TCP sockets does not guarantee that the data are actually transmitted or that the remote computer will pass that data to the other client in a timely fashion. Using a flush function will guarantee that DCRTCP.LIB places the data onto the network. No guarantee is made that the remote client will receive that data. sock_flushnext() is the most efficient of the flush functions. It causes the next function that sends data to the socket to flush, meaning the data will be transmitted immediately. Several functions imply a flush and do not require an additional flush: sock_puts(), and sometimes sock_putc() (when passed a \n).
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

None.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_write, sock_fastread, sock_read, sockerr, sock_flush, sock_flushnext

Chapter 7: Function Reference

159

sock_getc
int sock_getc( tcp_Socket *s );
DESCRIPTION

Gets the next character from the socket. NOTE: This function blocks. Starting with Dynamic C 7.05, this function is only valid with TCP sockets. Prior to 7.05, this function could not be used on UDP sockets after sock_recv_init() was called.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

Character read or -1 if error.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_putc, sock_gets, sock_puts, sock_read, sock_write


EXAMPLE

do { if (sock_bytesready( s ) > 0) putchar( sock_getc( s )); } while (tcp_tick(s));

160

TCP/IP Users Manual

sock_gets
int sock_gets( tcp_Socket *s, char *text, int len );
DESCRIPTION

Reads a string from a socket and replaces the CR or LF with a '\0'. If the string is longer than len, the string is null terminated and the remaining characters in the string are discarded. To use sock_gets(), you must first set ASCII mode using the function sock_mode()or the macro tcp_set_ascii(). Starting with Dynamic C 7.05, this function is only valid for TCP sockets. Prior to 7.05, this function could not be used on UDP sockets after sock_recv_init() was called.
PARAMETERS

s text len
RETURN VALUE

Pointer to a socket Buffer to put the string. Max length of buffer.

0: Either the buffer is empty or the buffer has room and the connection can get more data, but no '\r' or '\n' was read. >0: The length of the string. -1: Function was called with a UDP socket ( valid for Dynamic C 7.05 and later).
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_puts, sock_putc, sock_getc, sock_read, sock_write


EXAMPLE

sock_mode( s, TCP_MODE_ASCII ); do { if (sock_bytesready( s ) > 0) { sock_gets( s, buffer, sizeof(buffer)-1 ); puts( buffer ); } } while (tcp_tick( s );

Chapter 7: Function Reference

161

sock_iface
byte sock_iface( void *s );
DESCRIPTION

Retrieve the interface number of an open socket. May return IF_ANY for unbound sockets.
PARAMETER

s
RETURN VALUE

Pointer to open TCP or UDP socket.

Interface number (0..IF_MAX-1). IF_ANY: If the socket is unbound.


LIBRARY

NET.LIB
SEE ALSO

tcp_extopen, udp_extopen, tcp_extlisten

162

TCP/IP Users Manual

sock_init
int sock_init( void );
DESCRIPTION

This function initializes the packet driver and DCRTCP.LIB using the compiler defaults for configuration. This function must be called before using other DCRTCP.LIB functions. The return value indicates whether the network is available. If the return code is 1or 3, then the network is not usable. If the return code is 2, then the network is usable because suitable fallbacks were defined; particularly MY_IP_ADDRESS. It is only possible to get return codes 2 or 3 is USE_DHCP is defined. Typically, return codes 2 or 3 mean that there is no DHCP server available within approximately 30 seconds from calling sock_init(). The time-out can be adjusted by setting the global variable _bootptimeout to a suitable value before calling sock_init(). If USE_DHCP and MY_IP_ADDRESS are both defined, then by default the global variable _survivebootp will be set to TRUE. If _survivebootp is set to FALSE before calling sock_init(), then the fallbacks will not be used. That is, return code 2 will never be returned. If you use ucos2.lib, be sure to call OSInit() before calling sock_init().
RETURN VALUE

0: OK. 1: Ethernet packet driver initialization failed. 2: DHCP failed, using fallback definitions. 3: DHCP failed, no fallbacks defined. Other: reserved.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Chapter 7: Function Reference

163

sock_mode
word sock_mode( void *s, word mode );
DESCRIPTION

Change some of the socket options. Depending on whether s is a TCP or UDP socket, you may pass ORd combinations of the following flags in the mode parameter. For a TCP socket, only the TCP_MODE_* flags are relevant. For a UDP socket, only the UDP_MODE_* flags are relevant. Do not use the wrong flags for the given socket type. It is more convenient, faster, and safer to use the macro equivalent, if it is only desired to change one mode at a time. If you use this function, then you must specify the setting of all relevant flags (TCP or UDP). The macros do not do socket locking so, strictly speaking, C/OS users should call this function.
TCP MODES:

TCP_MODE_ASCII | TCP_MODE_BINARY (default)


TCP and UDP sockets are usually in binary mode which means an arbitrary stream of bytes is allowed (TCP is treated as a byte stream and UDP is treated as records filled with bytes.) The default is TCP_MODE_BINARY. By changing the mode to TCP_MODE_ASCII, some of the DCRTCP.LIB functions will see a stream of records terminated with a newline character. In ASCII mode, sock_bytesready() will return -1 until a newline-terminated string is in the buffer or the buffer is full. sock_puts() will append a newline to any output. sock_gets() (which should only be used in ASCII mode) removes the newline and null terminates the string. Equivalent Macros: tcp_set_binary(s) and tcp_set_ascii(s)

TCP_MODE_NAGLE (default) | TCP_MODE_NONAGLE


The Nagle algorithm may substantially reduce network traffic with little negative effect on a user (In some situations, the Nagle algorithm even improves application performance.) The default is TCP_MODE_NAGLE. This mode only affects TCP connections. Equivalent Macros: tcp_set_nagle(s) and tcp_set_nonagle(s)

164

TCP/IP Users Manual

sock_mode (continued)
UDP MODES:

UDP_MODE_CHK | UDP_MODE_NOCHK
Checksums are required for TCP, but not for UDP. The default is UDP_MODE_CHK. If you are providing a checksum at a higher level, the lowlevel checksum may be redundant. The checksum for UDP can be disabled by selecting the UDP_MODE_NOCHK flag. Note that you do not control whether the remote computer will send checksums. If that computer does checksum its outbound data, DCRTCP.LIB will check the received packet's checksum. Equivalent Macros: udp_set_chk(s) and udp_set_nochk(s)

UDP_MODE_NOICMP (default) | UDP_MODE_ICMP


Marks this socket for receipt of ICMP error messages. The messages are queued like normal received datagrams, and read using udp_recvfrom(), which returns -3 when ICMP messages are returned instead of normal datagrams. Only ICMP messages which are relevant to the current binding of the socket are queued. Equivalent Macros: udp_set_noicmp(s) and udp_set_icmp(s)

UDP_MODE_NODICMP (default) | UDP_MODE_DICMP


Marks this socket as the default receiver of ICMP messages which cannot be assigned to a particular UDP socket. This would be used for UDP sockets that are used with many different sendto addresses, since the ICMP message may refer to a message sent some time ago (with different destination address than the most recent). Only one UDP socket should be set with this mode. Equivalent Macros: udp_set_nodicmp(s) and udp_set_dicmp(s)
PARAMETERS

s mode
RETURN VALUE

Pointer to a socket. New mode for specified socket.

Resulting mode flags.


SEE ALSO

inet_addr
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Chapter 7: Function Reference

165

sock_noflush
void sock_noflush( tcp_Socket *s );
DESCRIPTION

This function prevents the next write to the socket from transmitting a data segment. It needs to be issued before each write function in which it is desired not to transmit. It can be used to make more efficient use of network bandwidth when the Nagle algorithm is turned off for the socket. If Nagle is on, then there is not much benefit to using this function.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

None.
SEE ALSO

sock_flush, sock_flushnext, sock_fastwrite, sock_write


LIBRARY

TCP.LIB

166

TCP/IP Users Manual

sock_perror
void sock_perror( void *s, const char *prefix );
DESCRIPTION

Prints out the most recent error messages for a socket, and clear the errors. This calls sockerr() and printf(), so it should only be called for debugging a new application. The output is in the format: [TCP|UDP] socket (ipaddr:port -> ipaddr:port) msg1; msg2 where msg1 and, possibly, msg2 are the most recent error messages. The initial string is "TCP" or "UDP" for open sockets, or may be "Closed" if the socket is currently closed (either TCP or UDP). Up to two error codes may be queued to a socket. If there are no errors, nothing is printed.
PARAMETERS

s prefix
LIBRARY

Pointer to TCP or UDP socket. Pointer to text to add to generated messages, or NULL.

NETERRNO.LIB
SEE ALSO

sock_error, sockerr

Chapter 7: Function Reference

167

sock_preread
int sock_preread( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

This function reads up to len bytes from the socket into the buffer dp. The bytes are not removed from the socket's buffer. This function is only valid with TCP sockets.
PARAMETERS

s dp len
RETURN VALUE

Pointer to a socket structure. Buffer to preread into. Maximum number of bytes to preread.

0: No data waiting. -1: Error. >0: Number of preread bytes.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_fastread, sock_fastwrite, sock_read, sock_write

168

TCP/IP Users Manual

sock_putc
byte sock_putc( tcp_Socket *s, byte c );
DESCRIPTION

A single character is placed on the output buffer. In the case of \n, the buffer is flushed as described under sock_flushnext. No other ASCII character expansion is performed. Note that sock_putc uses sock_write, and thus may block if the output buffer is full. See sock_write for more details. Starting with Dynamic C 7.05, this function is only valid with TCP sockets.
PARAMETERS

s c
RETURN VALUE

Pointer to a socket. Character to send.

The character c.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_read, sock_write, sock_fastread, sock_fastwrite, sock_mode

Chapter 7: Function Reference

169

sock_puts
int sock_puts( tcp_Socket *s, byte *dp );
DESCRIPTION

A string is placed on the output buffer and flushed as described under sock_flushnext(). If the socket is in ASCII mode, CR and LF are appended to the string. No other ASCII character expansion is performed. In binary mode, the string is sent as is. Note that sock_puts() uses sock_write(), and thus may block if the output buffer is full. See sock_write() for more details. Starting with Dynamic C 7.05, this function is only valid with TCP sockets.
PARAMETERS

s dp
RETURN VALUE

Pointer to a socket. Buffer to read the string from.

0: Length of string in dp. -1: Function was called with a UDP socket (valid for Dynamic C 7.05 and later).
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_gets, sock_putc, sock_getc, sock_read, sock_write

170

TCP/IP Users Manual

sock_rbleft
int sock_rbleft( void *s );
DESCRIPTION

Determines the number of bytes available in the receive buffer.


PARAMETERS

s
RETURN VALUE

Pointer to a socket.

Number of bytes available in the receive buffer.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_rbsize, sock_rbused, sock_tbsize, sock_tbused, sock_tbleft

Chapter 7: Function Reference

171

sock_rbsize
int sock_rbsize( void *s );
DESCRIPTION

Determines the size of the receive buffer for the specified socket.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

The size of the receive buffer.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_rbleft, sock_rbused, sock_tbsize, sock_tbused, sock_tbleft

172

TCP/IP Users Manual

sock_rbused
int sock_rbused( void *s );
DESCRIPTION

Returns the number of bytes in use in the receive buffer for the specified socket.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

Number of bytes in use.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_rbleft, sock_tbsize, sock_tbused, sock_tbleft

Chapter 7: Function Reference

173

sock_read
int sock_read( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

Reads up to len bytes from dp on socket s. This function will busy wait until either len bytes are read or there is an error condition. If sock_yield() has been called, the user-defined function that is passed to it will be called in a tight loop while sock_read() is busy waiting. Starting with Dynamic C 7.05, this function is only valid for TCP sockets. For UDP sockets, use udp_recv() or udp_recvfrom(). Prior to 7.05, this function cannot be used on UDP sockets after sock_recv_init() is called.
PARAMETERS

s dp len
RETURN VALUE

Pointer to a socket. Buffer to store bytes that are read. Maximum number of bytes to write to the buffer.

0: Success, number of bytes read.. -1: Error.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_fastread, sock_fastwrite, sock_write, sockerr, udp_recv, udp_recvfrom


EXAMPLE

Note that sock_fastread() and sock_read() do not necessarily return a complete or single linethey return blocks of bytes. In comparison, sock_getc() returns a single byte at a time and thus yields poor performance. do { len = sock_bytesready( s ); if (len > 0) { if (len > sizeof( buffer) - 1) // If too many bytes, read some len = sizeof( buffer ) - 1; // now, read the rest next time. sock_read( s, buffer, len ); buffer[ len ] = 0; printf( "%s", buffer ); } } while ( tcp_tick( s ));
174 TCP/IP Users Manual

sock_recv
int sock_recv( sock_type *s, char *buffer, int len );
DESCRIPTION

After a UDP socket is initialized with udp_open() and sock_recv_init(), sock_recv() scans the buffers for any datagram received by that socket. This function is not available starting with Dynamic C 7.05 (see Section 3.5).
PARAMETERS

s buffer maxlength
RETURN VALUE

Pointer to a UDP socket. Buffer to put datagram. Length of buffer.

>0: Length of datagram. 0: No datagram found. -1: Receive buffer not initialized with sock_recv_init().
LIBRARY

DCRTCP.LIB
SEE ALSO

sock_recv_from, sock_recv_init

Chapter 7: Function Reference

175

EXAMPLE USING SOCK_RECV()

// Old way of setting network addresses are commented out //#define MY_IP_ADDRESS "10.10.6.100" //#define MY_NETMASK "255.255.255.0" // New way of setting network addresses. #define TCPCONFIG 1 #memmap xmem #use "dcrtcp.lib" #define SAMPLE 401 udp_Socket data; char bigbuf[ 8192 ]; main() { word templen; char spare[ 1500 ]; sock_init(); if ( !udp_open( &data, SAMPLE, 0xffffffff, SAMPLE, NULL) { puts("Could not open broadcast socket"); exit( 3 ); } /* set large buffer mode */ if ( sock_recv_init( &data, bigbuf, sizeof( bigbuf ))) { puts("Could not enable large buffers"); exit( 3 ); } sock_mode( &data, UDP_MODE_NOCHK ); while (1) { tcp_tick( NULL ); if (templen = sock_recv(&data, spare, sizeof(spare ))) { /* something received */ printf("Got %u byte packet\n", templen ); } } } // turn off checksums

176

TCP/IP Users Manual

sock_recv_from
int sock_recv_from( sock_type *s, long *hisip, word *hisport, char *buffer, int len );
DESCRIPTION

After a UDP socket is initialized with udp_open() and sock_recv_init(), sock_recv_from () scans the buffers for any datagram received by that socket and identifies the remote hosts address. This function is not available starting with Dynamic C 7.05 (see Section 3.5).
PARAMETERS

s hisip hisport buffer len


RETURN VALUE

Pointer to UDP socket. IP of remote host, according to UDP header. Port of remote host. Buffer to put datagram in. Length of buffer.

>0: Length of datagram received. 0: No datagram. -1: Receive buffer was not initialized with sock_recv_init().
LIBRARY

DCRTCP.LIB
SEE ALSO

sock_recv, sock_recv_init

Chapter 7: Function Reference

177

sock_recv_init
int sock_recv_init( sock_type *s, void *space, word len );
DESCRIPTION

This function is not available starting with Dynamic C 7.05 (see Section 3.5). The basic socket reading functions (sock_read(), sock_fastread(), etc.) are not adequate for all your UDP needs. The most basic limitation is their inability to treat UDP as a record service. A record service must receive distinct datagrams and pass them to the user program as such. You must know the length of the received datagram and the sender (if you opened in broadcast mode). You may also receive the datagrams very quickly, so you must have a mechanism to buffer them. Once a socket is opened with udp_open(), you can use sock_recv_init() to initialize that socket for sock_recv() and sock_recv_from(). Note that sock_recv() and related functions are incompatible with sock_read(), sock_fastread(), sock_gets() and sock_getc(). Once you have used sock_recv_init(), you can no longer use the older-style calls. sock_recv_init() installs a large buffer area which gets segmented into smaller buffers. Whenever a UDP datagram arrives, DCRTCP.LIB stuffs that datagram into one of these new buffers. The new functions scan those buffers. You must select the size of the buffer you submit to sock_recv_init(); make it as large as possible, say 4K, 8K or 16K. For a sample program, see Example using sock_recv() listed under sock_recv().
PARAMETERS

s space len
RETURN VALUE

Pointer to a UDP socket. Buffer of temporary storage space to store newly received packets. Size of the buffer.

0
LIBRARY

DCRTCP.LIB
SEE ALSO

sock_recv_from, sock_recv

178

TCP/IP Users Manual

sock_resolved
int sock_resolved( void *s );
DESCRIPTION

Check whether the socket has a valid destination hardware address. This is typically used for UDP sockets, but may also be used for TCP sockets. If this function returns zero (FALSE), then any datagrams you send using udp_send() or udp_sendto() may not be transmitted because the destination hardware address is not known. If the current destination IP address of the socket is zero (i.e., the socket is passively opened), this function returns zero, since datagrams cannot be transmitted from a passively opened socket. If udp_bypass_arp() is in effect, the return value from this function is unaffected, however datagrams will still be sent to the specified hardware address (since the normal resolve process is bypassed). Note that a hardware address may become invalid after being valid, since the underlying ARP table may need to purge the entry. This would be rare, but if any UDP application needs to ensure that all packets are actually transmitted, which is a questionable goal since UDP is unreliable, then this function should be consulted before each send. If this function returns 0, then the UDP socket should be re-opened. The hardware address may also be invalidated if udp_sendto() is called with a different destination IP address, that has not been determined based on an incoming datagram. This function is not required for TCP sockets, since the TCP library handles these details internally.
PARAMETER

s
RETURN VALUE:

Pointer to open TCP or UDP socket

0: Destination hardware address not valid. !0: Destination hardware address resolved OK.
LIBRARY

NET.LIB
SEE ALSO

udp_extopen, arpresolve_start, arpresolve_check, udp_waitopen, udp_sendto, udp_bypass_arp

Chapter 7: Function Reference

179

sock_set_tos
void sock_set_tos( void *s, byte tos );
DESCRIPTION

Set the IP Type Of Service field in outgoing packets for this socket. The given TOS will be in effect until the socket is closed. When a socket is opened (or re-opened), the TOS will be set to the default (TCP_TOS or UDP_TOS as appropriate). If not overridden, the defaults are zero (IPTOS_DEFAULT) in both cases.
PARAMETERS

s tos

Pointer to open TCP or UDP socket. Type Of Service. This should be one of the following values:

IPTOS_DEFAULT - Default service IPTOS_CHEAP - Minimize monetary cost IPTOS_RELIABLE - Maximize reliability IPTOS_CAPACIOUS - Maximize throughput IPTOS_FAST - Minimize delay IPTOS_SECURE - Maximize security.

Other value may be used (since TOS is just a number between 0 and 255), but this should only be done for experimental purposes.
LIBRARY

NET.LIB
SEE ALSO

sock_set_ttl

180

TCP/IP Users Manual

sock_set_ttl
void sock_set_ttl( void *s, byte ttl );
DESCRIPTION

Set the IP Time To Live field in outgoing packets for this socket. The given TTL will be in effect until the socket is closed. When a socket is opened (or re-opened), the TTL will be set to the default (TCP_TTL or UDP_TTL as appropriate). If not overridden, the defaults are 64 in both cases.
PARAMETERS

s ttl

Pointer to open TCP or UDP socket. Time To Live. This is a value between 1 and 255. A value of zero is also accepted, but will have undesirable consequences.

LIBRARY

NET.LIB
SEE ALSO

sock_set_tos

Chapter 7: Function Reference

181

sockstate
char *sockstate( void *s );
DESCRIPTION

Returns a string that gives the current state for a socket.


PARAMETERS

s
RETURN VALUE

Pointer to a socket.

An ASCII message which represents the current state of the socket. These strings should not be modified. Listen" indicates a passively opened socket that is waiting for a connection. "SynSent" and "SynRcvd" are connection phase intermediate states. "Established" states that the connection is complete. "EstClosing" "FinWait1" "FinWait2" "CloseWait" "Closing" "LastAck" "TimeWait" and "CloseMSL" are connection termination intermediate states. "Closed" indicates that the connection is completely closed. "UDP Socket" is always returned for UDP sockets because they are stateless. "Not an active socket" is a default value used when the socket is not recognized as UDP or TCP. "BAD" more than one bit set.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_established, sock_dataready
EXAMPLE

char *p; ... #ifdef DEBUG if ( p = sockstate( s )) printf("Socket state is '%s'\n\r", p ); #endif DEBUG

182

TCP/IP Users Manual

sock_tbleft
int sock_tbleft( void *s );
DESCRIPTION

Gets the number of bytes left in the transmit buffer. If you do not wish to block, you may first query how much space is available for writing by calling this function before generating data that must be transmitted. This removes the need for your application to also buffer data.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

Number of bytes left in the transmit buffer.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_rbsize, sock_rbused, sock_rbleft, sock_tbsize, sock_tbused

if ( sock_tbleft( s ) > 10 ) { /* we can send up to 10 bytes without blocking or overflowing */ ... }

Chapter 7: Function Reference

183

sock_tbsize
int sock_tbsize( void *s );
DESCRIPTION

Determines the size of the transmit buffer for the specified socket.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

The size of the transmit buffer.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_rbsize, sock_rbused, sock_rbleft, sock_tbleft, sock_tbused

184

TCP/IP Users Manual

sock_tbused
int sock_tbused( void *s );
DESCRIPTION

Gets the number of bytes in use in the transmit buffer for the specified socket.
PARAMETERS

s
RETURN VALUE

Pointer to a socket.

Number of bytes in use.


LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_rbsize, sock_rbused, sock_rbleft, sock_tbsize, sock_tbleft

Chapter 7: Function Reference

185

sock_tick
void sock_tick( void *s, int *optional_status_ptr );
DESCRIPTION

This macro calls tcp_tick() to quickly check incoming and outgoing data and to manage all the open sockets. If our particular socket, s, is either closed or made inoperative due to an error condition, sock_tick() sets the value of *optional_status_ptr (if the pointer is not NULL) to 1, then jumps to a local, user-supplied label, sock_err. If the socket connection is fine and the pointer is not NULL *optional_status_ptr is set to 0.
PARAMETERS

s optional_status_ptr
RETURN VALUE

Pointer to a socket. Pointer to status word.

None.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

186

TCP/IP Users Manual

sock_wait_closed
void sock_wait_closed( void *s, int seconds, int (*fptr)(), int *status );
DESCRIPTION

This macro waits until a TCP connection is fully closed. Returns immediately for UDP sockets. On an error, the macro jumps to a local, user-supplied sock_err label. If fptr returns non-zero the macro returns with the status word set to the value of fptrs return value. This macro has been deprecated in Dynamic C version 7.20.
PARAMETERS

s seconds

Pointer to a socket. Number of seconds to wait before timing out. A value of zero indicates the macro should never time-out. A good value to use is sock_delay, a system variable set on configuration. Typically sock_delay is about 20 seconds, but can be set to something else in main(). Function to call repeatedly while waiting. This is a user-supplied function. Pointer to a status word.

fptr

status
RETURN VALUE

None.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Chapter 7: Function Reference

187

sock_wait_established
void sock_wait_established( void *s, int seconds, int (*fptr)(), int *status );
DESCRIPTION

This macro waits until a connection is established for the specified TCP socket, or aborts if a time-out occurs. It returns immediately for UDP sockets. On an error, the macro jumps to the local, user-supplied sock_err label. If fptr returns non-zero, the macro returns. This macro has been deprecated in Dynamic C version 7.20.
PARAMETERS

s seconds

Pointer to a socket. Number of seconds to wait before timing out. A value of zero indicates the macro should never time-out. A good value to use is sock_delay, a system variable set on configuration. Typically sock_delay is about 20 seconds, but can be set to something else in main(). Function to call repeatedly while waiting. This is a user-supplied function. Pointer to a status word.

fptr

status
RETURN VALUE

None.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

188

TCP/IP Users Manual

sock_wait_input
void sock_wait_input( void *s, int seconds, int (*fptr)(), int *status );
DESCRIPTION

Waits until input exists for functions such as sock_read() and sock_gets(). As described under sock_mode(), if in ASCII mode, sock_wait_input only returns when a complete string exists or the buffer is full. It returns immediately for UDP sockets. On an error, the macro jumps to a local, user-supplied sock_err label. If fptr returns non-zero, the macro returns. This macro has been deprecated in Dynamic C version 7.20.
PARAMETERS

s seconds

Pointer to a socket. Number of seconds to wait before timing out. A value of zero indicates the macro should never time-out. A good value to use is sock_delay, a system variable set on configuration. Typically sock_delay is about 20 seconds, but can be set to something else in main(). Function to call repeatedly while waiting. A pointer to the status word. If this parameter is NULL, no status number will be available, but the macro will otherwise function normally. Typically the pointer will point to a local signed integer that is used only for status. status may be tested to determine how the socket was ended. A value of 1 means a proper close while a -1 value indicates a reset or abort.

fptr status

RETURN VALUE

None.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Chapter 7: Function Reference

189

sock_write
int sock_write( tcp_Socket *s, byte *dp, int len );
DESCRIPTION

Writes up to len bytes from dp to socket s. This function busy waits until either the buffer is completely written or a socket error occurs. If sock_yield() has been called, the user-defined function that is passed to it will be called in a tight loop while sock_write() is busywaiting. For UDP, sock_write() will send one (or more) records. For TCP, the new data may be transmitted if enough data is in the buffer or sufficient time has expired or the user has explicitly used sock_flushnext() to indicate this data should be flushed immediately. In either case, there is no guarantee of acceptance at the other end. Starting with Dynamic C 7.05, this function is only valid for TCP sockets. For UDP sockets, use udp_send() or udp_sendto().
PARAMETERS

s dp len
RETURN VALUE

Pointer to a socket. Pointer to a buffer. Maximum number of bytes to write to the buffer.

Number of bytes written or -1 on an error.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

sock_read, sock_fastwrite, sock_fastread, sockerr, sock_flush, sock_flushnext, udp_send, udp_sendto

190

TCP/IP Users Manual

sock_xfastread
int sock_xfastread( tcp_Socket *s, long dp, long len );
DESCRIPTION

Reads up to len bytes from dp on socket s. If possible this function fills the buffer, otherwise only the number of bytes immediately available if any are returned. This function is only valid for TCP sockets. For UDP sockets, use udp_recv() or udp_recvfrom(). This function is identical to sock_fastread(), except that it reads into an extended memory buffer.
PARAMETERS

s dp

Pointer to socket. Buffer to place bytes that are read, as an xmem address obtained from, for example, xalloc(). Maximum number of bytes to write to the buffer.

len
RETURN VALUE

Number of bytes read or -1 if there was an error.


LIBRARY

TCP.LIB
SEE ALSO

sock_read, sock_fastwrite, sock_write, sockerr, udp_recv, udp_recvfrom, sock_fastread

Chapter 7: Function Reference

191

sock_xfastwrite
int sock_xfastwrite( tcp_Socket *s, long dp, long len );
DESCRIPTION

Writes up to len bytes from dp to socket s. This function writes as many bytes possible to the socket and returns that number of bytes. This function is only valid for TCP sockets. For UDP sockets, use udp_send() or udp_sendto(). This function is identical to sock_fastwrite(), except that an extended memory data source is used.
PARAMETERS

s dp

Pointer to socket. Buffer containing data to be written, as an xmem address obtained from, for example, xalloc(). Maximum number of bytes to write to the socket.

len
RETURN VALUE

Number of bytes written or -1 if there was an error.


LIBRARY

TCP.LIB
SEE ALSO

sock_write, sock_fastread, sock_read, sockerr, sock_flush, sock_flushnext, udp_send, udp_sendto, sock_fastwrite

192

TCP/IP Users Manual

sock_yield
int sock_yield( tcp_Socket *s, void (*fn)() );
DESCRIPTION

This function, if called prior to one of the blocking functions, will cause fn, the userdefined function that is passed in as the second parameter, to be called repeatedly while the blocking function is in a busywait state.
PARAMETERS

s fn
RETURN VALUE

Pointer to a TCP socket. User-defined function.

0
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)

Chapter 7: Function Reference

193

tcp_clearreserve
void tcp_clearreserve( word port );
DESCRIPTION

This function causes DCRTCP to handle a socket connection to the specified port normally. This undoes the action taken by tcp_reserveport().
PARAMETERS

port
RETURN VALUE

Port to use.

None.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

tcp_open, tcp_listen, tcp_reserveport

194

TCP/IP Users Manual

tcp_config
void tcp_config( char *name, char *value );
DESCRIPTION

Sets TCP/IP stack parameters at runtime. It should not be called with open sockets. Note that there are specific (and safer) functions for modifying some of the common parameters. This function is deprecated. It is highly recommended that you do NOT use it, since it uses strings, hence taking up lots of root data storage.
PARAMETERS

name

Setting to be changed. The possible parameters are: MY_IP_ADDRESS: host IP address (use sethostid() instead) MY_NETMASK MY_GATEWAY: hosts default gateway MY_NAMESERVER: hosts default nameserver MY_HOSTNAME MY_DOMAINNAME: hosts domain name (use setdomainname() instead)

value
RETURN VALUE

The value to assign to name.

None.
LIBRARY

NET.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

tcp_open, sock_close, sock_abort, sethostid, setdomainname, sethostname

Chapter 7: Function Reference

195

tcp_extlisten
int tcp_extlisten( tcp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, word reserved, long buffer, int buflen );
DESCRIPTION

This function tells DCRTCP that an incoming session for a particular port will be accepted. The buffer and buflen parameters allow a user to supply a socket buffer, instead of using a socket buffer from the pool. tcp_extlisten() is an extended version of tcp_listen().
PARAMETERS

s iface

Pointer to the sockets data structure. Local interface on which to open the socket. Use IF_ANY if the socket is to accept connections from any interface. Otherwise, connections will be accepted only from the specified interface. Prior to Dynamic C 7.30 this parameter was not implemented and should be IF_DEFAULT.

lport remip port datahandler

Port to listen on. IP address to accept connections from or 0 for all. Port to accept connections from or 0 for all. Function to call when data is received, NULL for placing data in the sockets receive buffer. Prior to Dynamic C 7.30, some details for implementation of this service had not been finalized. Insert a value of NULL if you are using a version of Dynamic C prior to 7.30. Set to 0 for now. This parameter is for compatibility and possible future use. Address of user-supplied socket buffer in xmem. This is the return value of xalloc(). If buffer is 0, the socket buffer for this socket is pulled from the buffer pool defined by the macro MAX_TCP_SOCKET_BUFFERS. Length of user-supplied socket buffer.

reserved buffer

buflen
RETURN VALUE

0: Failure. 1: Success.
LIBRARY

TCP.LIB
196 TCP/IP Users Manual

tcp_extopen
int tcp_extopen( tcp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, long buffer, int buflen );
DESCRIPTION

Actively creates a session with another machine. The buffer and buflen parameters allow a user to supply a socket buffer, instead of using a socket buffer from the pool. tcp_extopen() is an extended version of tcp_open(). s iface Pointer to sockets data structure. Local interface on which to open the socket. Use IF_ANY if interface is to be selected automatically based on the destination IP address. Our port, zero for the next one available in the range 1025-65536. IP address to connect to. Port to connect to. Function to call when data is received, NULL for placing data in the sockets receive buffer. Prior to Dynamic C 7.30, some details for implementation of this service had not been finalized. Insert a value of NULL if you are using a version of Dynamic C prior to 7.30. Address of user-supplied socket buffer in xmem. This is the return value of xalloc(). If buffer is 0, the socket buffer for this socket is pulled from the buffer pool defined by the macro MAX_TCP_SOCKET_BUFFERS. Length of user-supplied socket buffer.

lport remip port datahandler

buffer

buflen
RETURN VALUE

0:Error, unable to resolve the remote computer's hardware address. !0: Success.
LIBRARY

TCP.LIB
SEE ALSO

tcp_open

Chapter 7: Function Reference

197

tcp_keepalive
int tcp_keepalive( tcp_Socket *s, long timeout );
DESCRIPTION

Enable or disable TCP keepalives on a specified socket. The socket must already be open. Keepalives will then be sent after timeout seconds of inactivity. It is highly recommended to keep timeout as long as possible, to reduce the load on the network. Ideally, it should be no shorter than 2 hours. After the timeout is sent, and KEEPALIVE_WAITTIME seconds pass, another keepalive will be sent, in case the first was lost. This will be retried KEEPALIVE_NUMRETRYS times. Both of these macros can be defined at the top of your program, overriding the defaults of 60 seconds, and 4 retries. Using keepalives is not a recommended procedure. Ideally, the application using the socket should send its own keepalives. tcp_keepalive() is provided because telnet and a few other network protocols do not have a method of sending keepalives at the application level.
PARAMETERS

s timeout

Pointer to a socket. Period of inactivity, in seconds, before sending a keepalive or 0 to turn off keepalives.

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

TCP.LIB
SEE ALSO

sock_fastread, sock_fastwrite, sock_write, sockerr

198

TCP/IP Users Manual

tcp_listen
int tcp_listen( tcp_Socket *s, word lport, longword remip, word port, dataHandler_t datahandler, word reserved );
DESCRIPTION

This function tells DCRTCP.LIB that an incoming session for a particular port will be accepted. After a call to tcp_listen(), the function sock_established() (or the macro sock_wait_established) must be called to poll the connection until a session is fully established. It is possible for a connection to be opened, written to and closed between two calls to the function sock_established(). To handle this case, call sock_bytesready() to determine if there is data to be read from the buffer. Multiple calls to tcp_listen() to the same local port (lport) are acceptable and constitute the mechanism for supporting multiple incoming connections to the same local port. Each time another host attempts to open a session on that particular port, another one of the listens will be consumed until such time as all listens have become established sessions and subsequent remote host attempts will receive a reset.
PARAMETERS

s lport remip

Pointer to a socket. Port to listen on (the local port number). IP address of the remote host to accept connections from or 0 for all. Port to accept connections from or 0 for all. Function to call when data is received; NULL for placing data in the socket's receive buffer. Prior to Dynamic C 7.30, some details for implementation of this service had not been finalized. Insert a value of NULL if you are using a version of Dynamic C prior to 7.30. Set to 0 for now. This parameter is for compatibility and possible future use.

port datahandler

reserved

RETURN VALUE

0: Failure. 1: Success.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

tcp_extlisten
Chapter 7: Function Reference 199

EXAMPLE USING TCP_LISTEN()

// Old way of setting network addresses is commented out. //#define MY_IP_ADDRESS "10.10.6.100" //#define MY_NETMASK "255.255.255.0" // New method of setting network addresses #define TCPCONFIG 1 #memmap xmem #use "dcrtcp.lib" #define TELNET_PORT 23 static tcp_Socket *s; char *userid; telnets(int port) { tcp_Socket telnetsock; char buffer[ 512 ]; int status; s = &telnetsock; tcp_listen( s, port, 0L, 0, NULL, 0); while (!sock_established(s) && sock_bytesready(s)==-1){ tcp_tick(NULL); } puts("Receiving incoming connection"); sock_mode( s, TCP_MODE_ASCII ); sock_puts( s, "Welcome to a sample telnet server."); sock_puts( s, "Each line you type will be printed on"\ " this screen once you hit return."); /* other guy closes connection except if we timeout ... */ do { if (sock_bytesready(s) >= 0) { sock_gets(s, buffer, sizeof(buffer)-1); puts ( buffer); } } while (tcp_tick(s)); } main() { sock_init(); telnets( TELNET_PORT); exit( 0 ); }

200

TCP/IP Users Manual

tcp_open
int tcp_open( tcp_Socket *s, word lport, longword remip, word port, dataHandler_t datahandler );
DESCRIPTION

This function actively creates a session with another machine. After a call to tcp_open(), the function sock_established() (or the macro sock_wait_established) must be called to poll the connection until a session is fully established. It is possible for a connection to be opened, written to and closed between two calls to the function sock_established(). To handle this case, call sock_bytesready() to determine if there is data to be read from the buffer.
PARAMETERS

s lport

Pointer to a socket structure. Our local port. Use zero for the next available port in the range 1025-65536. A few applications will require you to use a particular local port number, but most network applications let you use almost any port with a certain set of restrictions. For example, FINGER or TELNET clients can use any local port value, so pass the value of zero for lport and let DCRTCP.LIB pick one for you. IP address to connect to. Port to connect to. Function to call when data is received; NULL for placing data in the sockets receive buffer. Prior to Dynamic C 7.30, some details for implementation of this service had not been finalized. Insert a value of NULL if you are using a version of Dynamic C prior to 7.30.

remip port datahandler

RETURN VALUE

0: Unable to resolve the remote computer's hardware address. !0 otherwise.


LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

tcp_listen

Chapter 7: Function Reference

201

EXAMPLE USING TCP_OPEN()

// Old way of setting network addresses is commented out. //#define MY_IP_ADDRESS "10.10.6.100" //#define MY_NETMASK "255.255.255.0" // New of setting network addresses #define TCPCONFIG 1 #memmap xmem #use "dcrtcp.lib" #define ADDRESS "10.10.6.19" #define PORT "200" main() { word status; word port; longword host; tcp_Socket tsock; sock_init(); if (!(host = resolve(ADDRESS))) { puts("Could not resolve host"); exit( 3 ); } port = atoi( PORT ); printf("Attempting to open '%s' on port %u\n\r", ADDRESS, port ); if ( !tcp_open( &tsock, 0, host, port , NULL )) { puts("Unable to open TCP session"); exit( 3 ); } printf("Waiting a maximum of %u seconds for connection"\ " to be established\n\r", sock_delay ); while (!sock_established(&tsock) && sock_bytesready(&tsock)== -1){ tcp_tick(NULL); } puts("Socket is established"); sock_close( &tsock ); exit( 0 ); }

202

TCP/IP Users Manual

tcp_reserveport
void tcp_reserveport( word port );
DESCRIPTION

This function allows a connection to be established even if there is not yet a socket available. This is done by setting a parameter in the TCP header during the connection setup phase that indicates 0 bytes of data can be received at the present time. The requesting end of the connection will wait until the TCP header parameter indicates that data will be accepted. The 2MSL waiting period for closing a socket is avoided by using this function. The penalty of slower connection times on a controller that is processing a large number of connections is offset by allowing the program to have less sockets and consequently less RAM usage.
PARAMETERS

port
RETURN VALUE

Port to use.

None.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

tcp_open, tcp_listen, tcp_clearreserve

Chapter 7: Function Reference

203

tcp_tick
int tcp_tick( void *s );
DESCRIPTION

This function is a single kernel routine designed to quickly process packets and return as soon as possible. tcp_tick() performs processing on all sockets upon each invocation: checking for new packets, processing those packets, and performing retransmissions on lost data. On most other computer systems and other kernels, performing these required operations in the background is often done by a task switch. DCRTCP.LIB does not use a tasker for its basic operation, although it can adopt one for the user-level services. Although you may ignore the returned value of tcp_tick(), it is the easiest method to determine the status of the given socket.
PARAMETERS

Pointer to a socket. If a NULL pointer is passed in the returned value should be ignored.

RETURN VALUE

0: Connection reset or closed by other host or NULL was passed in. !0: Connection is fine.
LIBRARY

TCP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

tcp_open, sock_close, sock_abort

204

TCP/IP Users Manual

udp_bypass_arp
void udp_bypass_arp( udp_Socket *s, eth_address *eth );
DESCRIPTION

Override the normal Address Resolution Protocol for this UDP socket. This is sometimes necessary for special purposes such as if the Ethernet address is to remain fixed, or if the Ethernet address is not obtainable using ARP. The great majority of applications should not use this function. If ARP bypass is in effect for a UDP socket, then udp_sendto() will never return the -2 return code. The destination interface is also forced to be IF_DEFAULT. If the supplied hardware address is accessible from a non-default interface only, then you will need to manually set the s->iface field.
PARAMETERS

s eth

UDP socket Pointer to override address. If NULL, then resume normal operation i.e., use ARP to resolve Ethernet addresses. Note that the specified Ethernet address must be in static storage, since only the pointer is stored.

LIBRARY

UDP.LIB
SEE ALSO

udp_sendto, udp_waitsend, sock_resolved

Chapter 7: Function Reference

205

udp_close
void udp_close( udp_Socket *ds );
DESCRIPTION

This function closes a UDP connection. Starting with Dynamic C 7.30, this function performs the actions necessary to leave a host group when closing a multicast socket. It is IGMPv2 compliant.
PARAMETERS

ds
LIBRARY

Pointer to sockets data structure.

UDP.LIB

206

TCP/IP Users Manual

udp_extopen
int udp_extopen( udp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, long buffer, int buflen );
DESCRIPTION

This function is an extended version of udp_open(). It opens a socket on a given network interface (iface) on a given local port (lport). If the remote IP address is specified (remip), then only UDP datagrams from that host will be accepted. The remote end of the connection is specified by remip and port. The following table explains the possible combinations and what they mean.

REMIP

Effect of REMIP value

The connection completes when the first datagram is received, supplying both the remote IP address and the remote port number. Only datagrams received from that IP/port address will be accepted. All remote hosts can send datagrams to the socket. All outgoing datagrams will be sent to the broadcast address unless udp_sendto() specifies otherwise. If the remote IP address is a valid IP address and the remote port is 0, the connection will complete when the first datagram is received, supplying the remote port number. If the remote IP address and the remote port are both specified when the function is called, the connection is complete at that point.

-1

>0

The buffer and buflen parameters allow a user to supply a socket buffer, instead of using a socket buffer from the pool. If remip is non-zero, then the process of resolving the correct destination hardware address is started. Datagrams cannot be sent until sock_resolved() returns TRUE. If you attempt to send datagrams before this, then the datagrams may not get sent. The exception to this is if remip is -1 (broadcast) in which case datagrams may be sent immediately after calling this function. This function also works with multicast addresses. If remip is a multicast address, then packets sent with this function will go to the multicast address, and packets received will also be from that multicast address. Also, if enabled, IGMP will be used to join the multicast groups. The group will be left when the socket is closed. Note that if port is 0 and remip is a multicast address, the port will not be filled in on the first received datagram (that is, the socket is non-binding to the port).
Chapter 7: Function Reference 207

udp_extopen (continued)
PARAMETERS

s iface

Pointer to socket. Local interface on which to open the socket. Use IF_ANY if the socket is to accept datagrams from any interface. Otherwise, datagrams will be accepted only from the specified interface. This parameter is supported as of Dynamic C 7.30. With earlier version of DC, this parameter should be IF_DEFAULT.

lport remip port datahandler

Local port. Acceptable remote IP, or 0 for all. Acceptable remote port, or 0 for all. Function to call when data is received, NULL for placing data in the sockets receive buffer. Address of user-supplied socket buffer in xmem. If buffer is 0, the socket buffer for this socket is pulled from the buffer pool defined by the macro MAX_UDP_SOCKET_BUFFERS. Length of user-supplied socket buffer.

buffer

buflen
RETURN VALUE:

!0: Success. 0: Failure; error opening socket, e.g., a buffer could not be allocated.
LIBRARY

UDP.LIB
SEE ALSO

udp_open, sock_resolved

208

TCP/IP Users Manual

udp_open
int udp_open( udp_Socket *s, word lport, longword remip, word port, dataHandler_t datahandler );
DESCRIPTION

This function opens a UDP socket on the given local port (lport). If the remote IP address is specified (remip), then only UDP datagrams from that host will be accepted. The remote end of the connection is specified by remip and port. The following table explains the possible combinations and what they mean.

REMIP

Effect of REMIP value

The connection completes when the first datagram is received, supplying both the remote IP address and the remote port number. Only datagrams received from that IP/port address will be accepted. All remote hosts can send datagrams to the socket. All outgoing datagrams will be sent to the broadcast address on the specified port. The port parameter is ignored. If the remote IP address is a valid IP address and the remote port is 0, the connection will complete when the first datagram is received, supplying the remote port number. If the remote IP address and the remote port are both specified when the function is called, the connection is complete at that point.

-1

>0

If the remote host is set to a particular address, either host may initiate traffic. Multiple calls to udp_open() with remip set to zero is a useful way of accepting multiple incoming sessions. Although multiple calls to udp_open() may normally be made with the same lport number, only one udp_open() should be made on a particular lport if the remip is set to -1. Essentially, the broadcast and nonbroadcast protocols cannot coexist. Be sure that you have allocated enough UDP socket buffers with MAX_UDP_SOCKET_BUFFERS. Note that this macro defaults to 0, so any usage of udp_open() requires a definition of MAX_UDP_SOCKET_BUFFERS in your program.

Chapter 7: Function Reference

209

udp_open (continued)
This function also works with multicast addresses. If remip is a multicast address, then packets sent with this function will go to the multicast address, and packets received will also be from that multicast address. Also, if enabled, IGMP will be used to join the multicast groups. The group will be left when the socket is closed. Note that if port is 0 and remip is a multicast address, the port will not be filled in on the first received datagram (that is, the socket is non-binding to the port).
PARAMETERS

s lport remip

Pointer to a UDP socket. Local port Acceptable remote IP, 0 to connect on first datagram, or -1 for broadcast. Acceptable remote port, or 0 to connect on first datagram. Function to call when data is received. NULL for placing data in the socket's receive buffer.

port datahandler

RETURN VALUE

0: Failure (e.g., a buffer could not be allocated). !0: Success.


LIBRARY

UDP.LIB (Prior to DC 7.05, this was DCRTCP.LIB)


SEE ALSO

udp_extopen

210

TCP/IP Users Manual

udp_peek
int udp_peek( udp_Socket *s, _udp_datagram_info *udi );
DESCRIPTION

Look into the UDP socket receive buffer to see if there is a datagram ready to be read using udp_recvfrom(). This function does not remove the datagram from the buffer, but it allows the application to determine the full details about the next datagram, including whether the datagram was broadcast. The returned data is put in *udi. udi must point to a valid data structure, or be NULL. The data structure is: typedef struct { longword remip; // word remport; // int len; // byte flags; // byte iface; // } _udp_datagram_info; Remote host IP address Remote host port number Length of datagram Bit mask (defined below) Interface number

The flags field may have one of the following values: UDI_ICMP_ERROR UDI_TOS_MASK UDI_BROADCAST_LL UDI_BROADCAST_IP This is an ICMP error entry. Type-of-service bit mask. Received on broadcast link layer address. Received on broadcast network (IP) address.

PARAMETERS

s udi
RETURN VALUE

UDP socket to check Where to store the returned information.

1: A normal datagram is in the receive buffer. 0: No datagram waiting. -3: ICMP error message in receive buffer - will only be returned if udi is not NULL.
LIBRARY

UDP.LIB
SEE ALSO

udp_recvfrom

Chapter 7: Function Reference

211

udp_recv
int udp_recv( udp_Socket *s, char *buffer, int len );
DESCRIPTION

Receives a single UDP datagram on a UDP socket. If the buffer is not large enough for the datagram, the datagram is truncated, and the remainder discarded.
PARAMETERS

s buffer len
RETURN VALUE

Pointer to sockets data structure. Buffer where the UDP datagram will be stored. Maximum length of the buffer.

0: Number of bytes received. -1: No datagram waiting. <-1: Error.


LIBRARY

UDP.LIB
SEE ALSO

udp_recvfrom, udp_send, udp_sendto, udp_open

212

TCP/IP Users Manual

udp_recvfrom
int udp_recvfrom( udp_Socket *s, char *buffer, int len, longword *remip, word *remport );
DESCRIPTION

Receive a single UDP datagram on a UDP socket. remip and remport should be pointers to the locations where the remote IP address and remote port from which the datagram originated are placed. If the buffer is not large enough for the datagram, then the datagram will be truncated, with the remainder being discarded. If and only if the UDP_MODE_ICMP or UDP_MODE_DICMP modes are set for this socket, then a return code of -3 indicates that an ICMP error message is being returned in the buffer instead of a normal datagram. In this case, buffer will contain fixed data in the form of a structure of type _udp_icmp_message. The definition of this structure is: typedef struct { word myport; // Originating port on this host byte icmp_type; // One of the ICMPTYPE_* values byte icmp_code; // The corresponding ICMP code } _udp_icmp_message; Please see sock_mode for more information about the modes UDP_MODE_ICMP and UDP_MODE_DICMP.
PARAMETERS

s buffer len remip remport


RETURN VALUE

Pointer to sockets data structure. Buffer where the UDP datagram will be stored. Maximum length of the buffer. IP address of the remote host of the received datagram. Port number of the remote host of the received datagram.

0: Number of bytes received. -1: No datagram waiting. -2: Error - not a UDP socket. -3: The returned buffer contains an ICMP error which was queued previously.
LIBRARY

UDP.LIB
SEE ALSO

udp_recv, udp_send, udp_sendto, udp_open, udp_peek


Chapter 7: Function Reference 213

udp_send
int udp_send( udp_Socket *s, char *buffer, int len );
DESCRIPTION

Sends a single UDP datagram on a UDP socket. It will not work for a socket for which the remip parameter to udp_open() was 0, unless a datagram has first been received on the socket. If the remip parameter to udp_open() was -1, the datagram will be send to the broadcast address.
PARAMETERS

s buffer len
RETURN VALUE

Pointer to sockets data structure. Buffer that contains the UDP datagram Length of the UDP datagram.

0: Number of bytes sent. -1: Failure. -2: Failed because hardware address not resolved.
LIBRARY

UDP.LIB
SEE ALSO

udp_sendto, udp_recv, udp_recvfrom, udp_open

214

TCP/IP Users Manual

udp_sendto
int udp_sendto( udp_Socket *s, char *buffer, int len, longword remip, word remport );
DESCRIPTION

Sends a single UDP datagram on a UDP socket. It will send the datagram to the IP address and port specified by remip and remport. Note that this function can be used on a socket that has been "connected" to a different remote host and port.
PARAMETERS

s buffer len remip remport


RETURN VALUE

Pointer to sockets data structure. Buffer that contains the UDP datagram. Length of the UDP datagram. IP address of the remote host. Port number of the remote host.

0: Success, number of bytes sent. -1: Failure. -2: Failed because hardware address not resolved.
LIBRARY

UDP.LIB
SEE ALSO

udp_send, udp_xsendto, udp_recv, udp_recvfrom, udp_open

Chapter 7: Function Reference

215

udp_waitopen
int udp_waitopen( udp_Socket *s, int iface, word lport, longword remip, word port, dataHandler_t datahandler, long buffer, int buflen, longword millisecs );
DESCRIPTION

This function is identical to udp_extopen(), except that it waits a specified amount of time for the hardware address of the destination to be resolved. While waiting, this function calls tcp_tick().
PARAMETERS

s iface

Pointer to socket. Local interface on which to open the socket. This parameter is supported as of Dynamic C 7.30. With earlier version of DC, this parameter should be IF_DEFAULT.

lport remip port datahandler

Local port. Acceptable remote ip, or 0 for all. Acceptable remote port, or 0 for all. Function to call when data is received, NULL for placing data in the sockets receive buffer. Address of user-supplied socket buffer in xmem, 0 to use a buffer from the socket buffer pool. Length of user-supplied socket buffer. Maximum milliseconds to wait for the hardware address to be resolved.

buffer

buflen millisecs

RETURN VALUE

>0: Successfully opened socket. 0: Timed out without resolving address. -1: Error opening socket (e.g., buffer could not be allocated).
LIBRARY

UDP.LIB
SEE ALSO

udp_extopen, sock_resolved

216

TCP/IP Users Manual

udp_waitsend
int udp_waitsend( udp_Socket *s, char *buffer, int len, longword remip, word remport, word millisecs );
DESCRIPTION

This is identical to udp_sendto(), except that it will block for up to the specified amount of time waiting for the hardware address to be resolved. Normally, you should not have to specify more than 100ms for the time out. If it takes longer than this, the destination is probably unavailable.
PARAMETERS

s buffer len remip remport millisecs

UDP socket on which to send the datagram. Buffer that contains the UDP datagram. Length of the UDP datagram. IP address of the remote host. Port number of the remote host. Number of milliseconds to wait for hardware address resolution. Reasonable values are between 50 and 750 milliseconds.

RETURN VALUE

0: Number of bytes sent. -1: Failure (invalid UDP socket etc.). -2: Failure (timed out, no datagram sent).
LIBRARY

UDP.LIB
SEE ALSO

udp_sendto, udp_recvfrom, udp_bypass_arp

Chapter 7: Function Reference

217

udp_xsendto
int udp_xsendto( udp_Socket *s, long buffer, int len, longword remip, word remport );
DESCRIPTION

Send a single UDP datagram on a UDP socket. It will send the datagram to the IP address specified by remip, and the port specified by remport. Note that this function can be used even on a socket that has been "connected" to a remote host and port. This function is identical to udp_sendto() except that the data address is specified as a physical address.
PARAMETERS

s buffer len remip remport


RETURN VALUE

UDP socket on which to send the datagram. Buffer that contains the UDP datagram. Length of the UDP datagram. IP address of the remote host. Port number of the remote host.

0: Number of bytes sent. -1: Failure. -2: Failure (hardware address not resolved).
LIBRARY

UDP.LIB
SEE ALSO

udp_send, udp_recv, udp_recvfrom, udp_open, udp_sendto

218

TCP/IP Users Manual

8. Server Utility Library


The server utility library, ZSERVER.LIB, contains the structures, functions, and constants to allow HTTP (Hypertext Transfer Protocol) and FTP (File Transfer Protocol) servers to share data and user authentication information while running concurrently. HTML form functionality is included in ZSERVER.LIB.

8.1 Data Structures for Zserver.lib


There are several data structures in this library of interest to developers of HTTP or FTP servers.

8.1.1 ServerSpec Structure


A file transfer server has access to a list of objects: files, functions and variables. This list is defined as a global array in ZSERVER.LIB. ServerSpec server_spec[SSPEC_MAXSPEC]; Throughout this manual, this array will be called the TCP/IP servers object list or sometimes the server spec list.

8.1.2 ServerAuth Structure


ZSERVER.LIB also defines a global array that is a list of user name/password pairs. ServerAuth server_auth[SAUTH_MAXUSERS]; Throughout this manual, this array will be called the TCP/IP users list or sometimes just users list.

8.1.3 FormVar Structure


An array of FormVar structures represent the variables in an HTML form. The developer will declare an array of these structures, with the size needed to hold all variables for a particular form. The FormVar structure contains:

A server_spec index that references the variable to be modified. This is the location of
the form variable in the TCP/IP servers object list.

An integrity-checking function pointer that ensures that the variables are set to valid values. High and low values (for numerical types). Length (for the string type, and for the maximum length of the string representations of values).

A Pointer to an array of values (for when the value must be one of a specific, and probably
short, list). The developer can specify whether she wants the variable to be set through a text entry field or a pull-down menu, and if the variable should be considered read-only. This FormVar array is placed in a ServerSpec structure using the function sspec_addform. ServerSpec entries that represent variables will be added to the FormVar
Chapter 8: Server Utility Library 219

array using sspec_addfv. Properties (e.g., the integrity-checking properties) for these FormVar entries can be set with various other functions. Hence, there is a level of indirection between the variables in the forms and the actual variables themselves. This allows the same variable to be included in multiple forms with different ranges for each form, and perhaps be read-only in one form and modifiable in another.

8.2 Constants Used in Zserver.lib


The constants in this section are values assigned to the fields of the structures ServerSpec and ServerAuth. They are used in the functions described in Section 8.4, some as function parameters and some as return values.

8.2.1 ServerSpec Type Field


This field describes the objects in the TCP/IP servers object list. SSPEC_ERROR SSPEC_FILE SSPEC_FSFILE SSPEC_FORM SSPEC_FUNCTION SSPEC_ROOTFILE SSPEC_UNUSED SSPEC_VARIABLE SSPEC_XMEMFILE SSPEC_ROOTVAR SSPEC_XMEMVAR // Error condition // Data resides in a file // The data resides in a file system file // Set of modifiable variables // Data is a function // Data resides in root memory // Indicates an unused entry // Data is a variable (for HTTP) // Data resides in extended memory // Data is a variable in root memory // Data is a variable in xmem

8.2.2 ServerSpec Vartype Field


If the object is a variable, then this field will tell you what type of variable it is: INT8, INT16, INT32, PTR16, FLOAT32

8.2.3 Servermask field


The type of server (HTTP and/or FTP) that has access to a particular data structure is determined by the servermask field. Both ServerSpec and ServerAuth have this field. It must be set when adding the structure to its array. The default is that no server has access. servermask can be one of the following, or any bitwise inclusive OR of these values: SERVER_FTP SERVER_HTTP SERVER_USER SERVER_WRITABLE

// for use with the flash file system. // server will allow client(s) to write to its files.

220

TCP/IP Users Manual

8.2.4 Configuration Macros


These constants define system limits on various data lengths and array sizes.

SAUTH_MAXNAME
Maximum length of strings in ServerAuth structure. Default is 20. Strings must include a null character, so with its default value of 20, strings in this structure may be at most 19 characters long

SAUTH_MAXUSERS
Maximum number of users for a TCP/IP users list. Default is 10.

SSPEC_MAXNAME
Maximum length of strings in a ServerSpec structure entry. Default is 20.

SSPEC_MAXSPEC
Sets the maximum number of entries in the global array, server_spec. Defaults to 10.

SSPEC_USERSPERRESOURCE
This macro defines the maximum number of users that can be associated per resource. Set to 1 by default.

SSPEC_XMEMVARLEN
Defines the size of the stack-allocated buffer used by sspec_readvariable() when reading a variable in xmem. It defaults to 20.

8.3 HTML Forms


Defining FORM_ERROR_BUF is required to use the HTML form functionality in ZSERVER.LIB. The value assigned to this macro is the number of bytes to reserve in root memory for the buffer used for form processing. This buffer must be large enough to hold the name and value for each variable, plus four bytes for each variable. An array of type FormVar must be declared to hold information about the form variables. Be sure to allocate enough entries in the array to hold all of the variables that will go in the form. If more forms are needed, then more of these arrays can be allocated. Please see Section 9.4.4 on page 320 for an example program.

8.4 API Functions


The server utility API functions are described in this section. These functions give servers a consistent interface to files, variables and client information.

Chapter 8: Server Utility Library

221

sauth_adduser
int sauth_adduser( char *username, char *password, word servermask );
DESCRIPTION

Adds a user to the TCP/IP users list.


PARAMETERS

username password servermask

Name of the user. Password for the user. Bitmask representing valid servers (e.g., SERVER_HTTP, SERVER_FTP).

RETURN VALUE

-1: Failure. 0: Success; index in TCP/IP users list (id passed to sauth_getusername()).
LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_authenticate, sauth_getwriteaccess, sauth_setwriteaccess, sauth_removeuser

222

TCP/IP Users Manual

sauth_authenticate
int sauth_authenticate( char *username, char *password, word server );
DESCRIPTION

Authenticate a user.
PARAMETERS

username password server

Name of user. Password for the user. The server for which this function is authenticating (e.g., SERVER_HTTP, SERVER_FTP).

RETURN VALUE

-1: Failure, user not valid. 0: Success, array index of the ServerAuth structure for authenticated user.
LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_adduser

Chapter 8: Server Utility Library

223

sauth_getpassword
sauth_getpassword(int userid);
DESCRIPTION

Get the password for a user.


PARAMETER

userid Return Value

Index into TCP/IP users list.

!=NULL: password string NULL: Failure


LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_setpassword

224

TCP/IP Users Manual

sauth_getuserid
int sauth_getuserid( char *username, word server );
DESCRIPTION

Gets the user index for a user.


PARAMETERS

username server
RETURN VALUE

User's name. Server for which we are looking up.

0: Success, index of user in the TCP/IP users list.


-1: Failure.
LIBRARY

ZSERVER.LIB

Chapter 8: Server Utility Library

225

sauth_getusername
char *sauth_getusername( int userid );
DESCRIPTION

Gets a pointer to username from the ServerAuth structure.


PARAMETERS

userid
RETURN VALUE

The users id, i.e., the array index in the TCP/IP users list.

NULL: Failure. !NULL: Success, pointer to the username string.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getusername

226

TCP/IP Users Manual

sauth_getwriteaccess
int sauth_getwriteaccess( int sauth );
DESCRIPTION

Checks whether or not a user has write access.


PARAMETERS

sauth
RETURN VALUE

Index of the user in the TCP/IP users list.

0: User does not have write access. 1: User has write access. -1: Failure.
LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_setwriteaccess

Chapter 8: Server Utility Library

227

sauth_removeuser
int sauth_removeuser( int userid );
DESCRIPTION

Remove the given user from the user list. IMPORTANT: Any associations of the given user with web pages should be changed. Otherwise, no one will have access to the unchanged web pages. Authentication can be turned off for a page with sspec_setrealm(sspec, "").
PARAMETERS

userid
RETURN VALUE

Index in TCP/IP users list.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_adduser

228

TCP/IP Users Manual

sauth_setpassword
int sauth_setpassword( int userid, char *password );
DESCRIPTION

Sets the password for a user.


PARAMETERS

userid password
RETURN VALUE

Index of user in TCP/IP users list. User's new password.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_getpassword

Chapter 8: Server Utility Library

229

230

TCP/IP Users Manual

sauth_setwriteaccess
int sauth_setwriteaccess( int sauth, int writeaccess );
DESCRIPTION

Sets the write accessibility of a user.


PARAMETERS

sauth writeaccess
RETURN VALUE

Index of the user in the TCP/IP users list. Set to 1 to give write access, 0 to deny write access.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_getwriteaccess

Chapter 8: Server Utility Library

231

sspec_addform
int sspec_addform( char *name, FormVar *form, int formsize, word servermask );
DESCRIPTION

Adds a form (set of modifiable variables) to the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry. This function is currently only useful for the HTTP server.
PARAMETERS

name form

Name of the new form. Pointer to the form array. This is a user-defined array to hold information about form variables. Size of the form array Bitmask representing valid servers (currently only useful with SERVER_HTTP)

formsize servermask

RETURN VALUE

0: Success; location of form in TCP/IP servers object list. -1: Failed to add form.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfsfile, sspec_addfunction, sspec_addrootfile, sspec_addvariable, sspec_addxmemvar, sspec_addxmemfile sspec_aliasspec, sspec_addfv

232

TCP/IP Users Manual

sspec_addfsfile
int sspec_addfsfile( char *name, byte filenum, word servermask );
DESCRIPTION

Adds a file, located in the file system, to the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry. This function associates a name with the file. For more information regarding the Flash File System, please see the Dynamic C Users Manual.
PARAMETERS

name filenum

Name of the new file. Number of the file in the file system. This is the number passed in as the 2nd parm to fcreate() or the return value from fcreate_unused(). Bitmask representing servers for which this entry will be valid (e.g., SERVER_HTTP, SERVER_FTP). If the file being added is a compressed file, SERVER_COMPRESSED must be ORed into the servermask value

servermask

RETURN VALUE

-1: Failure. 0: Success; location of file in TCP/IP servers object list.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addrootfile, sspec_addfunction, sspec_addvariable, sspec_addxmemfile, sspec_addform, sspec_aliasspec

Chapter 8: Server Utility Library

233

sspec_addfunction
int sspec_addfunction( char *name, void (*fptr)(), word servermask );
DESCRIPTION

Adds a function to the list of objects recognized by the server. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry. This function is currently only useful for HTTP servers.
PARAMETERS

name (*ftpr)() servermask


RETURN VALUE

Name of the function. Pointer to the function. Bitmask representing servers for which this function will be valid (currently only useful with SERVER_HTTP).

-1: Failure. 0: Success, location of the function in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addform, sspec_addfsfile, sspec_addrootfile, sspec_addvariable, sspec_addxmemvar, sspec_addxmemfile, sspec_aliasspec

234

TCP/IP Users Manual

sspec_addfv
int sspec_addfv( int form, int var );
DESCRIPTION

Adds a variable to a form.


PARAMETERS

form var
RETURN VALUE

Index of the form in the TCP/IP servers object list. Index of the variable in the TCP/IP servers object list.

-1: Failure. 0: Success; next available index into the FormVar array.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addform

Chapter 8: Server Utility Library

235

sspec_addrootfile
int sspec_addrootfile( char *name, char *fileloc, int len, word servermask );
DESCRIPTION

Adds a file that is located in root memory to the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry.
PARAMETERS

name fileloc len servermask

Name of the new file. Pointer to the beginning of the file. Length of the file in bytes. Bitmask representing servers for which this entry will be valid (e.g., SERVER_HTTP, SERVER_FTP).

RETURN VALUE

-1: Failure. 0: Success; file index in the TCP/IP servers object list is returned.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfsfile, sspec_addxmemfile, sspec_addxmemvar, sspec_addvariable, sspec_addfunction, sspec_addform, sspec_aliasspec, sspec_resizerootfile

236

TCP/IP Users Manual

sspec_adduser
int sspec_adduser(int sspec, int userid);
DESCRIPTION

Adds a user to the list of users that have access to the the given spec entry. Up to SSPEC_USERSPERRESOURCE users can be added. Any more than that will result in this function returning -1.
PARAMETERS

sspec userid
RETURN VALUE

Location of object in TCP/IP servers object list. Location of the user in the TCP/IP users list.

0: Success, index of userid added for given spec entry.


-1: Failure.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setuser, sspec_getusername, sspec_getuserid, sspec_removeuser

Chapter 8: Server Utility Library

237

sspec_addvariable
int sspec_addvariable( char *name, void *variable, word type, char *format, word servermask );
DESCRIPTION

Adds a variable to the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry. This function is currently only useful for the HTTP server.
PARAMETERS

name variable type format servermask

Name of the new variable. Address of actual variable. Type of the variable (e.g., INT8, INT16, PTR16, etc.). Output format of the variable. Bitmask representing servers for which this function will be valid (currently only useful with SERVER_HTTP).

RETURN VALUE

-1: Failure. 0: Success, the location of the variable in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfsfile, sspec_addrootfile, sspec_addxmemfile, sspec_addxmemvar, sspec_addfunction sspec_addform, sspec_aliasspec

238

TCP/IP Users Manual

sspec_addxmemfile
int sspec_addxmemfile( char *name, long fileloc, word servermask );
DESCRIPTION

Adds a file, located in extended memory, to the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry.
PARAMETERS

name fileloc

Name of the new file. Location of the beginning of the file. The first 4 bytes of the file must represent the length of the file (#ximport does this automatically). Bitmask representing servers for which this entry will be valid (e.g., SERVER_HTTP, SERVER_FTP). If the file being added is a compressed file, SERVER_COMPRESSED must be ORed into the servermask value.

servermask

RETURN VALUE

-1: Failure. 0: Success, the location of the file in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfsfile, sspec_addrootfile, sspec_addvariable, sspec_addxmemvar, sspec_addfunction, sspec_addform, sspec_aliasspec

Chapter 8: Server Utility Library

239

sspec_addxmemvar
int sspec_addxmemvar( char *name, long variable, word type, char *format, word servermask );
DESCRIPTION

Add a variable located in extended memory to the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry. Currently, this function is useful only for the HTTP server.
PARAMETERS

name variable type format servermask

Name of the new variable. Address of the variable in extended memory. Variable type (e.g., INT8, INT16, PTR16, etc.). Output format of the variable. Bitmask representing valid servers (currently only useful with SERVER_HTTP).

RETURN VALUE

-1: Failure. 0: Success, the location of the variable in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfsfile, sspec_addrootfile, sspec_addvariable, sspec_addfunction, sspec_addform, sspec_addxmemfile, sspec_aliasspec

240

TCP/IP Users Manual

sspec_aliasspec
int sspec_aliasspec( int sspec, char *name );
DESCRIPTION

Creates an alias to an existing object in the TCP/IP servers object list. Make sure that SSPEC_MAXSPEC is large enough to hold this new entry. Please note, this is NOT a deep copy. That is, any file, variable, or form that the alias references will be the same copy of the file, variable, or form that already exists in the TCP/IP servers object list. This should be called only when the original entry has been completely set up.
PARAMETERS

sspec

Location of the object in the TCP/IP servers object list that will be aliased. Name field of the ServerSpec structure that will be aliased.

name
RETURN VALUE

-1: Failure. 0: Success; return location of alias, i.e., new index.


LIBRARY

ZSERVER.LIB

See also
sspec_addform, sspec_addfsfile, sspec_addfunction, sspec_addrootfile, sspec_addvariable, sspec_addxmemfile

Chapter 8: Server Utility Library

241

sspec_checkaccess
int sspec_checkaccess( int sspec, int userid );
DESCRIPTION

This function checks whether or not the specified user has permission to access the specified object in the TCP/IP servers object list.
PARAMETERS

sspec userid
RETURN VALUE

Location of object in TCP/IP servers object list. Location of the user in the TCP/IP users list.

0: User does not have access. 1: User has access. -1: Failure.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_needsauthentication

242

TCP/IP Users Manual

sspec_findfv
int sspec_findfv( int form, char *varname );
DESCRIPTION

Finds the index in the array of type FormVar of a form variable in a given form.
PARAMETERS

form varname
RETURN VALUE

Location of the form in the TCP/IP servers object list. Name of the variable to find.

-1: Failure. 0: Success; the index of the form variable in the array of type FormVar.
LIBRARY

ZSERVER.LIB

Chapter 8: Server Utility Library

243

sspec_findname
int sspec_findname( char *name, word server );
DESCRIPTION

Finds the location of the object associated with name and returns the location (index into the server_spec array) of the object if the server is allowed access to it. (Access is determined by the servermask field in the ServerSpec structure for the object.)
PARAMETERS

name server
RETURN VALUE

Name to search for in the TCP/IP servers object list. The server making the request (e.g., SERVER_HTTP).

-1: Failure. 0: Success, location of the object in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_findnextfile

244

TCP/IP Users Manual

sspec_findfsname
int sspec_findfsname( byte filenum, word server );
DESCRIPTION

Find the server spec entry for filenum. The entry must be of type SSPEC_FSFILE and be allowed with the specified server.
PARAMETERS

filenum

File to search for. This value is the number passed in as the 2nd parm to fcreate() or the return value from fcreate_unused(). The server making the request (e.g., SERVER_HTTP).

server
RETURN VALUE

-1: Failure. 0: Success, location of the object in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_findname

Chapter 8: Server Utility Library

245

sspec_findnextfile
int sspec_findnextfile( int start, word server );
DESCRIPTION

Finds the first ServerSpec structure in the array, at or following the structure indexed by start, that is associated with a file and that is accessible by the server.
PARAMETERS

start server
RETURN VALUE

The array index at which to begin the search. The server making the request (e.g., SERVER_HTTP).

-1: Failure. 0: Success, index of requested ServerSpec structure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_findname

246

TCP/IP Users Manual

sspec_getfileloc
long sspec_getfileloc( int sspec );
DESCRIPTION

Gets the location in memory or in the file system of a file represented by a ServerSpec structure. The location of the file is returned as a long. The return value should be cast to the appropriate type by the user:

char* for a root file FileNum for the file system


sspec_getfiletype() can be used to find the file type.
PARAMETERS

sspec
RETURN VALUE

Index into the array of ServerSpec structures.

0: Success, location of the file. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfiletype, sspec_getlength

Chapter 8: Server Utility Library

247

sspec_getfiletype
word sspec_getfiletype( int sspec );
DESCRIPTION

Gets the type of a file represented by a ServerSpec structure.


PARAMETERS

sspec
RETURN VALUE

Index into the array of ServerSpec structures.

SSPEC_ERROR: Failure. !SSPEC_ERROR: Success, type of file. See Section 8.2.1 for possible return values.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfileloc, sspec_gettype

248

TCP/IP Users Manual

sspec_getformtitle
char *sspec_getformtitle( int form );
DESCRIPTION

Gets the title for an automatically generated form.


PARAMETERS

form
RETURN VALUE

server_spec index of the form.

NULL: Failure. !NULL: Success, title string.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setformtitle

Chapter 8: Server Utility Library

249

sspec_getfunction
void *sspec_getfunction( int sspec );
DESCRIPTION

Accesses the array of ServerSpec structures to get a pointer to the requested function.
PARAMETERS

sspec
RETURN VALUE

Index into the array of ServerSpec structures.

NULL: Failure. !NULL: Success, pointer to requested function.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfunction

250

TCP/IP Users Manual

sspec_getfvdesc
char *sspec_getfvdesc( int form, int var );
DESCRIPTION

Gets the description of a variable that is displayed in the HTML form table.
PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable.

NULL: Failure. !NULL: Success, description string.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvdesc

Chapter 8: Server Utility Library

251

sspec_getfventrytype
int sspec_getfventrytype( int form, int var );
DESCRIPTION

Gets the type of form entry element that should be used for the given variable.
PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable.

-1: Failure; Type of form entry element on success: HTML_FORM_TEXT is a text box. HTML_FORM_PULLDOWN is a pull-down menu.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfventrytype

252

TCP/IP Users Manual

sspec_getfvlen
int sspec_getfvlen( int form, int var );
DESCRIPTION

Gets the length of a form variable (the maximum length of the string representation of the variable).
PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable.

-1: Failure. 0: Success, length of the variable.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvlen

Chapter 8: Server Utility Library

253

sspec_getfvname
char *sspec_getfvname( int form, int var );
DESCRIPTION

Gets the name of a variable that is displayed in the HTML form table.
PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index into the array of FormVar structures of the variable.

NULL: Failure. !NULL, name of the form variable.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvname

254

TCP/IP Users Manual

sspec_getfvnum
int sspec_getfvnum( int form );
DESCRIPTION

Gets the number of variables in a form.


PARAMETERS

form
RETURN VALUE

server_spec index of the form.

-1: Failure. 0: Success, number of form variables.


LIBRARY

ZSERVER.LIB

Chapter 8: Server Utility Library

255

sspec_getfvopt
char *sspec_getfvopt( int form, int var, int option );
DESCRIPTION

Gets the numbered option (starting from 0) of the form variable. This function is only valid if the form variable has the option list set.
PARAMETERS

form var option


RETURN VALUE

server_spec index of the form. Index into the array of FormVar structures of the variable. Index of the form variable option.

NULL: Failure. !NULL: Success, form variable option.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvoptlist, sspec_getfvoptlistlen

256

TCP/IP Users Manual

sspec_getfvoptlistlen
int sspec_getfvoptlistlen( int form, int var );
DESCRIPTION

Gets the length of the options list of the form variable. This function is only valid if the form variable has the option list set.
PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable.

-1: Failure. >0: Success, length of the options list.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfvopt, sspec_setfvoptlist

Chapter 8: Server Utility Library

257

sspec_getfvreadonly
int sspec_getfvreadonly( int form, int var );
DESCRIPTION

Checks if a form variable is read-only.


PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable.

0: Not read-only. 1: Read-only. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvreadonly

258

TCP/IP Users Manual

sspec_getfvspec
int sspec_getfvspec( int form, int var );
DESCRIPTION

Gets the server_spec index of a variable in a form.


PARAMETERS

form var
RETURN VALUE

server_spec index of the form. Index into the array of FormVar structures of the variable.

-1: Failure. 0: Success, location of the form variable in the TCP/IP servers object list.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addfv

Chapter 8: Server Utility Library

259

sspec_getlength
long sspec_getlength( int sspec );
DESCRIPTION

Gets the length of the file associated with the specified ServerSpec structure.
PARAMETERS

sspec
RETURN VALUE

Location of file in TCP/IP servers object list.

-1: Failure. 0: Success, length of the file in bytes.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_readfile, sspec_getfileloc

260

TCP/IP Users Manual

sspec_getname
char *sspec_getname( int sspec );
DESCRIPTION

Accesses the array of ServerSpec structures and returns a pointer to the objects name.
PARAMETERS

sspec
RETURN VALUE

Location of object in TCP/IP servers object list.

NULL: Failure. !NULL: Success, pointer to name string.


LIBRARY

ZSERVER.LIB

Chapter 8: Server Utility Library

261

sspec_getpreformfunction
void *sspec_getpreformfunction( int form );
DESCRIPTION

Gets the user function that will be called just before HTML form generation. This function is useful mainly for custom form generation functions.
PARAMETERS

form
RETURN VALUE

spec index of the form

NULL: No user function. !NULL: Pointer to user function.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setpreformfunction, sspec_setformfunction

262

TCP/IP Users Manual

sspec_getrealm
char *sspec_getrealm( int sspec );
DESCRIPTION

Returns the realm for the object.


PARAMETERS

sspec
RETURN VALUE

Location of the object in the TCP/IP servers object list.

NULL: Failure. !NULL: Success, pointer to the realm string.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setrealm

Chapter 8: Server Utility Library

263

sspec_gettype
word sspec_gettype( int sspec );
DESCRIPTION

Gets the type field of a ServerSpec structure.


PARAMETERS

sspec
RETURN VALUE

Location of the object in the TCP/IP servers object list.

SSPEC_ERROR: Failure. type field: Success (See Constants Used in Zserver.lib on page 220). For files and variables, it returns the generic type SSPEC_FILE or SSPEC_VARIABLE, respectively.
LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfiletype, sspec_getvartype

264

TCP/IP Users Manual

sspec_getuserid
int sspec_getuserid(int sspec, int index);
DESCRIPTION

Returns a userid for the given sspec resource. Since a resource can have multiple userids associated with it, index indicates which userid should be returned. Note that index should follow the relation 0 index < SSPEC_USERSPERRESOURCE. If there is no userid for a given index, -1 will be returned. If -1 is returned for an index, then -1 will also be returned for all higher indexes.
PARAMETERS

sspec index
RETURN VALUE

spec index index of userid for this sspec resource to return

-1: Error, or no such userid. 0: Success, userid is returned.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getusername, sauth_getusername

Chapter 8: Server Utility Library

265

sspec_getusername
char *sspec_getusername( int sspec );
DESCRIPTION

Gets the username field of the first ServerAuth structure indexed in the User ID array of the specified spec entry. If multiple users are associated with this resource, the first user's username will be returned. See sspec_getuserid() to get all userids for a resource, and sauth_getusername() to convert the userids to usernames.
PARAMETERS

sspec
RETURN VALUE

Index in TCP/IP servers object list.

NULL: Failure. !=NULL: Success, pointer to username.


LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_adduser, sspec_setuser, sauth_getuserid, sauth_getusername

266

TCP/IP Users Manual

sspec_getvaraddr
void *sspec_getvaraddr( int sspec );
DESCRIPTION

Returns a pointer to the requested variable in the TCP/IP servers object list.
PARAMETERS

sspec
RETURN VALUE

Location of the variable in the TCP/IP servers object list.

NULL: Failure. !NULL: Success, pointer to variable.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_readvariable

Chapter 8: Server Utility Library

267

sspec_getvarkind
word sspec_getvarkind( int sspec );
DESCRIPTION

Returns the kind of variable represented by sspec (INT8, INT16, INT32, FLOAT32, or PTR16).
PARAMETERS

sspec
RETURN VALUE

Location of the variable in the TCP/IP servers object list.

0: Failure. INT8|INT16|INT32|FLOAT32|PTR16: Success.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getvaraddr, sspec_getvartype, sspec_gettype

268

TCP/IP Users Manual

sspec_getvartype
word sspec_getvartype( int sspec );
DESCRIPTION

Gets the type of the variable in the TCP/IP servers object list.
PARAMETERS

sspec
RETURN VALUE

Location of the variable in the TCP/IP servers object list.

SSPEC_ERROR: Failure. SSPEC_ROOTVAR or SSPEC_XMEMVAR: Success.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getvaraddr, sspec_getvarkind, sspec_gettype

Chapter 8: Server Utility Library

269

sspec_needsauthentication
int sspec_needsauthentication( int sspec );
DESCRIPTION

Checks if an object in the TCP/IP servers object list needs user authentication to permit access. There is a field in the ServerSpec structure that is an index into the array of ServerAuth structures (list of valid users). If this field has a value, access to the object is limited to the one user specified.
PARAMETERS

sspec
RETURN VALUE

Index into the array of ServerSpec structures.

0: Does not need authentication. 1: Does need authentication. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getrealm

270

TCP/IP Users Manual

sspec_readfile
int sspec_readfile( int sspec, char *buffer, long offset, int len );
DESCRIPTION

Read a file (represented by the sspec index) into buffer, starting at offset, and only copying len bytes. For xmem files, this function automatically skips the first 4 bytes. Hence, an offset of 0 marks the beginning of the file contents, not the file length.
PARAMETERS

sspec buffer offset

Index into the array of ServerSpec structures. The buffer to put the file contents into. The offset from the start of the file, in bytes, at which copying should begin. The number of bytes to copy.

len
RETURN VALUE

-1: Failure. 0: Success, number of bytes copied.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getlength, sspec_getfileloc

Chapter 8: Server Utility Library

271

sspec_readvariable
int sspec_readvariable( int sspec, char *buffer );
DESCRIPTION

Formats the variable associated with the specified ServerSpec structure, and puts a NULL-terminated string representation of it in buffer. The macro SSPEC_XMEMVARLEN (default is 20) defines the size of the stack-allocated buffer when reading a variable in xmem.
PARAMETERS

sspec buffer
RETURN VALUE

Index into the array of ServerSpec structures. The buffer in which to put the variable.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getvaraddr

272

TCP/IP Users Manual

sspec_remove
int sspec_remove( int sspec );
DESCRIPTION

Removes an object from the TCP/IP servers object list.


PARAMETERS

sspec
RETURN VALUE

Index into the array of ServerSpec structures.

0: Success. -1: Failure (i.e., the index is already unused).


LIBRARY

ZSERVER.LIB

Chapter 8: Server Utility Library

273

sspec_removeuser
int sspec_removeuser(int sspec, int userid);
DESCRIPTION

Removes a user (specified by userid) from the list of users that have access to the object identified by sspec.
PARAMETERS

sspec userid
RETURN VALUE

spec index user index

0: Success, user was removed. -1: Failure, no such userid found.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setuser, sspec_adduser, sspec_getusername, sspec_getuserid

274

TCP/IP Users Manual

sspec_resizerootfile
int sspec_resizerootfile( int spec_index, int new_size );
DESCRIPTION

Change the byte size of a SSPEC item stored in root memory. Item must be a ROOTFILE, thus the item must have been created with sspec_addrootfile().
PARAMETERS

spec_index new_size
RETURN VALUE

spec index of the item New size to assign to item.

0: Successfully adjust size of item. -1: Failed to adjust size.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_addrootfile

Chapter 8: Server Utility Library

275

sspec_restore
int sspec_restore( void );
DESCRIPTION

Restores the TCP/IP servers object list and the TCP/IP users list (and some user-specified data if set up with sspec_setsavedata()) from the file system. This does not restore the actual files and variables, but only the structures that reference them. If the files are stored in flash, then the references will still be valid. Files in volatile RAM and variables must be rebuilt through other means.
RETURN VALUE

0: Successfully restored the server_spec and server_auth tables. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_save, sspec_setsavedata

276

TCP/IP Users Manual

sspec_save
int sspec_save( void );
DESCRIPTION

Saves the servers object list and server authorization list (along with some user-specified data if set up with sspec_setsavedata()) to the file system. This does not save the actual files and variables, but only the structures that reference them. If the files are stored in flash, then the references will still be valid. Files in volatile RAM and variables must be rebuilt through other means.
RETURN VALUE

0: Successfully save the server_spec and server_auth tables. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_restore, sspec_setsavedata

Chapter 8: Server Utility Library

277

sspec_setformepilog
int sspec_setformepilog( int form, int function );
DESCRIPTION

Sets the user-specified function that will be called when the form has been successfully submitted. This function can, for example, execute a cgi_redirectto to redirect to a specific page. It should accept "HttpState* state" as an argument, return 0 when it is not finished, and 1 when it is finished (i.e., behave like a normal CGI function).
PARAMETERS

form function

Index into the array of ServerSpec structures. Index into the array of ServerSpec structures. This is the return value of the function sspec_addfunction().

RETURN VALUE

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setformprolog

278

TCP/IP Users Manual

sspec_setformfunction
int sspec_setformfunction( int form, void (*fptr)() );
DESCRIPTION

Sets the function that will generate the form.


PARAMETERS

form fptr
RETURN VALUE

server_spec index of the form. Form generation function (NULL for the default function).

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB

Chapter 8: Server Utility Library

279

sspec_setformprolog
int sspec_setformprolog( int form, int function );
DESCRIPTION

Allows a user-specified function to be called just before form variables are updated. This is useful for implementing locking on the form variables (which can then be unlocked in the epilog function), so that other code will not update the variables during form processing. The user-specified function should accept "HttpState* state" as an argument, return 0 when it is not finished, and 1 when it is finished (i.e., behave like a normal CGI function).
PARAMETERS

form function

Index into the array of ServerSpec structures. Index into the array of ServerSpec structures. This is the return value of sspec_addfunction().

RETURN VALUE

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setformepilog

280

TCP/IP Users Manual

sspec_setformtitle
int sspec_setformtitle( int form, char *title );
DESCRIPTION

Sets the title for an automatically generated form.


PARAMETERS

form title
RETURN VALUE

server_spec index of the form. Pointer to the title of the HTML page.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getformtitle

Chapter 8: Server Utility Library

281

sspec_setfvcheck
int sspec_setfvcheck( int form, int var, int (*varcheck)() );
DESCRIPTION

Sets a function that can be used to check the integrity of a variable. The function should return 0 if there is no error, or !0 if there is an error.
PARAMETERS

form var varcheck


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Pointer to integrity-checking function.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvfloatrange, sspec_setfvoptlist, sspec_setfvrange

282

TCP/IP Users Manual

sspec_setfvdesc
int sspec_setfvdesc( int form, int var, char *desc );
DESCRIPTION

Sets the description of a variable that is displayed in the HTML form table.
PARAMETERS

form var desc


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Description of the variable. This text will display on the html page.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfvdesc

Chapter 8: Server Utility Library

283

sspec_setfventrytype
int sspec_setfventrytype( int form, int var, int entrytype );
DESCRIPTION

Sets the type of form entry element that should be used for the given variable.
PARAMETERS

form var entrytype

server_spec index of the form. Index (into the FormVar array) of the variable. HTML_FORM_TEXT for a text box, HTML_FORM_PULLDOWN for a pull-down menu. The default is HTML_FORM_TEXT.

RETURN VALUE

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfventrytype

284

TCP/IP Users Manual

sspec_setfvfloatrange
int sspec_setfvfloatrange( int form, int var, float low, float high );
DESCRIPTION

Sets the range of a float.


PARAMETERS

form var low high


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Minimum value of the variable. Maximum value of the variable.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvrange, sspec_setfvoptlist

Chapter 8: Server Utility Library

285

sspec_setfvlen
int sspec_setfvlen( int form, int var, int len );
DESCRIPTION

Sets the length of a form variable (the maximum length of the string representation of the variable). Note that for string variables, len should NOT include the NULL terminator.
PARAMETERS

form var len


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Length of the variable.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfvlen

286

TCP/IP Users Manual

sspec_setfvname
int sspec_setfvname( int form, int var, char *name );
DESCRIPTION

Sets the name of a variable that is displayed in the HTML form table.
PARAMETERS

form var name


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Display name of the variable.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfvname

Chapter 8: Server Utility Library

287

sspec_setfvoptlist
int sspec_setfvoptlist( int form, int var, char *list[], int listlen );
DESCRIPTION

Sets an enumerated list of possible values for a string variable.


PARAMETERS

form var list[] listlen


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Array of string values that the variable can assume. Length of the array.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfvopt, sspec_getfvoptlistlen, sspec_setfvfloatrange, sspec_setfvrange

288

TCP/IP Users Manual

sspec_setfvrange
int sspec_setfvrange( int form, int var, long low, long high );
DESCRIPTION

Sets the range of an integer.


PARAMETERS

form var low high


RETURN VALUE

server_spec index of the form. Index (into the FormVar array) of the variable. Minimum value of the variable. Maximum value of the variable.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_setfvfloatrange, sspec_setfvoptlist

Chapter 8: Server Utility Library

289

sspec_setfvreadonly
int sspec_setfvreadonly( int form, int var, int readonly );
DESCRIPTION

Sets the form variable to be read-only.


PARAMETERS

form var readonly

server_spec index of the form. Index (into the FormVar array) of the variable. 0 for read/write (this is the default); 1 for read-only.

RETURN VALUE

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getfvreadonly

290

TCP/IP Users Manual

sspec_setpreformfunction
int sspec_setpreformfunction( int form, void (*fptr)() );
DESCRIPTION

Sets a user function that will be called just before form generation. The user function is not called when the form is being generated because of errors in the form input. The user function must have the following prototype: void userfunction(int form); The function may not use the parameter, but it is useful if the same user function is used for multiple forms.
PARAMETERS

form fptr
RETURN VALUE

Spec index of the form. Pointer to user function to be called just before form generation

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getpreformfunction

Chapter 8: Server Utility Library

291

sspec_setrealm
int sspec_setrealm( int sspec, char *realm );
DESCRIPTION

Sets the realm field of a ServerSpec structure for HTTP authentication purposes. Setting this field enables authentication for the given entry in the TCP/IP servers object list. Authentication can be turned off again by passing "" as the realm parameter to this function.
PARAMETERS

sspec realm
RETURN VALUE

Index into the array of ServerSpec structures. Name of the realm.

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_getrealm

292

TCP/IP Users Manual

sspec_setsavedata
int sspec_setsavedata( char *data, unsigned long len, void *fptr );
DESCRIPTION

Sets user-supplied data that will be saved in addition to the spec and user authentication tables when sspec_save() is called.
PARAMETERS

data len fptr

Pointer to location of user-supplied data. Length of the user-supplied data in bytes. Pointer to a function that will be called when the user-supplied data has been restored.

RETURN VALUE

0: Successfully set up the user-supplied data. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sspec_save, sspec_restore

Chapter 8: Server Utility Library

293

sspec_setuser
int sspec_setuser( int sspec, int userid );
DESCRIPTION

Sets the user (owner) of a ServerSpec structure.


PARAMETERS

sspec userid
RETURN VALUE

Index into the array of ServerSpec structures. Index into the array of ServerAuth structures (identifies user).

0: Success. -1: Failure.


LIBRARY

ZSERVER.LIB
SEE ALSO

sauth_adduser, sspec_getusername

294

TCP/IP Users Manual

9. HTTP Server
An HTTP (Hypertext Transfer Protocol) server makes HTML (Hypertext Markup Language) pages and other documents available to clients ( i.e., web browsers). HTTP is implemented by HTTP.LIB. The general outline for an HTTP server looks like this: #define TCPCONFIG 1 //Pre-7.30 way of setting network addresses. //#define MY_IP_ADDRESS "10.10.6.107" //#define MY_NETMASK "255.255.255.0" #memmap xmem #use "dcrtcp.lib" #use "http.lib" /* Here is where you must set up the files etc. that the web server may access. */ main(){ sock_init(); http_init(); tcp_reserveport(80); while (1) { http_handler(); } } Both ways of setting network addresses are shown in the above code. The pre-Dynamic C 7.30 method is commented out. Starting with Dynamic C 7.30, setting up the network addresses is both more complex and more simple. The complexity lies in the added support for multiple interfaces. Luckily for us, the simplicity is in the interface to this more intricate implementation. In the file tcp_config.lib are predefined configurations that may be accessed by a #define of the macro TCPCONFIG. For instructions on how to set up different configurations, please see Section 2.2.2 or look in the file \LIB\TCPIP\TCP_CONFIG.LIB.

Chapter 9: HTTP Server

295

9.1 HTTP Server Data Structures


There are four data structures in HTTP.LIB of interest to developers of HTTP servers. They are discussed in this section.

9.1.1 HttpSpec
The HttpSpec data structure contains all the files, variables, and functions that the Web server may access. typedef struct { word type; char name[HTTP_MAXNAME]; long data; void *addr; word vartype; char *format; HttpRealm *realm; } HttpSpec; The structure ServerSpec from ZSERVER.LIB may be used instead. If only ZSERVER.LIB functionality is used in the server, save code space by including the statement: #define HTTP_NO_FLASHSPEC in the code before inclusion of HTTP.LIB.

9.1.1.1 HttpSpec fields


type This field tells the server if the entry is a file, variable or function (HTTPSPEC_FILE, HTTPSPEC_VARIABLE or HTTPSPEC_FUNCTION, respectively). This field specifies a unique name for referring to the entry. The Web server recognizes /index.html as the entity that matches http://someurl.com/index.html, and delivers the entrys content based on the value of type (the first field). The third field is the physical address of the entity. The fourth field is a short pointer to the entity. Either the third field or the fourth field is valid, not both. All files must use the physical address, variables and functions use the short pointer. This field describes the type of variable. Supported types are : INT8 INT16, PTR16, INT32, and FLOAT32. If the type field is not HTTPSPEC_VARIABLE, the vartype field is ignored. The format field describes the printf format specifier used to display the variable. This field is the name and password required to access the entity.

name

data addr

vartype

format realm

296

TCP/IP Users Manual

9.1.2 HttpType
The structure HttpType associates a file extension with a MIME type (Multipurpose Internet Mail Extension) and a function that handles the MIME type. Users can override HTTP_MAXNAME (defaults to 20 characters) in their source file. If the function pointer given is NULL, then the default handler (which sends the content verbatim) is used. typedef struct { char extension[10]; char type[HTTP_MAXNAME]; int (*fptr)(/* HttpState* */); } HttpType; For example, to create an HTTP server that can serve files with html or gif extensions, the following declaration is required in the application code: const HttpType http_types[] = { { ".html", "text/html", NULL}, { ".gif", "image/gif", NULL} };

9.1.3 HttpRealm
The structure HttpRealm holds user ID and password pairs for partitions called realms. These realms allow the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme and/or authorization database. typedef struct { char username[HTTP_MAXNAME]; char password[HTTP_MAXNAME]; char realm[HTTP_MAXNAME]; } HttpRealm; In the HttpSpec structure, there is a pointer to a structure of type HttpRealm. To passwordprotect the entity, add the name, password, and realm desired. If you do not want to password-protect the entity, leave the realm pointer in the HttpSpec structure NULL.

9.1.3.1 Authentication Methods


HTTP/1.0 Basic Authentication is used by default. This scheme is not a secure method of user authentication across an insecure network (e.g., the Internet). HTTP/1.0 does not, however, prevent additional authentication schemes and encryption mechanisms from being employed to increase security. Starting with Dynamic C version 8.xx, HTTP Digest Authentication as specified in RFC 2617 is supported. Instead of sending the password in cleartext as is done using Basic Authentication, MD5 is used to perform a cryptographic hash. To use HTTP Digest Authentication, define USE_HTTP_DIGEST_AUTHENTICATION as 1. When this USE_* macro is defined, the macros HTTP_MAX_NONCES and HTTP_DIGEST_NONCE_TIMEOUT are available; they affect negogiation time between server and client. For more details see Section 9.2 "Configuration Macros."
Chapter 9: HTTP Server 297

9.1.4 HttpState
Use of this structure is necessary for CGI functions. Some of the fields are off-limits to developers. The field that are available for use are described in Section 9.1.4.1 "HttpState Fields." typedef struct { tcp_Socket s; /* State information */ char state, nextstate, laststate; int substate, subsubstate; /* File referenced */ HttpSpecAll spec, subspec; HttpType *type; int (*handler)(), (*exec)(); /* rx/tx state variables */ long offset; long length; long filelength, subfilelength; long pos, subpos; long timeout, main_timeout; char buffer[HTTP_MAXBUFFER]; char *p; char peek[7]; char peeklen; /* HTTP request and header information */ char method; char url[HTTP_MAXURL]; char version; char connection; char content_type[40]; long content_length; char has_form; char finish_form; char abort_notify; char cancel; char username[HTTP_MAXNAME]; char password[HTTP_MAXNAME]; char cookie[HTTP_MAXNAME]; int headerlen; int headeroff; /* Other - don't touch */ char tag[HTTP_MAXNAME]; char value[HTTP_MAXNAME]; char authenticated;

298

TCP/IP Users Manual

/* Support for conditional SSI (error feedback, etc.) */ int cond[HTTP_MAX_COND]; /* Condition numbers (default 0) */ /* ZImport state structure -- Only included if zimport.lib has been #use'd */ union { SSpecFileHandle s; #ifdef __ZIMPORT_LIB ZFILE z; #endif } file; char close_needed; /* Optional User Data. Cleared on every new connection. */ #ifdef HTTP_USERDATA_SIZE char userdata[ HTTP_USERDATA_SIZE]; #endif } HttpState;

9.1.4.1 HttpState Fields


The fields discussed here are available for developers to use in their application programs. s This is the socket associated with the given HTTP server. A developer can use this in a CGI function to output dynamic data. Any of the TCP functions can be used. Intended for holding the current state of a state machine for a CGI function. That is, if a CGI function relinquishes control back to the HTTP server, then the values in these variables will be preserved for the next http_handler() call, in which the CGI function will be called again. These variables are initialized to 0 before the CGI function is called for the first time. Hence, the first state of a state machine using substate should be 0. This value can be used by the CGI function to implement an internal time-out. This value holds the timeout that is used by the web server. The web server checks against this timeout on every call of http_handler(). When the web server changes states, it resets main_timeout. When it has stayed in one state for too long, it cancels the current processing for the server and goes back to the initial state. Hence, a CGI function may want to reset this timeout if it needs more processing time (but care should be taken to make sure that the server is not locked up forever). This can be achieved like this:
state->main_timeout = set_timeout(HTTP_TIMEOUT);

substate subsubstate

timeout

main_timeout

HTTP_TIMEOUT is the number of seconds until the web server will time out. It is 16 seconds by default.
Chapter 9: HTTP Server 299

buffer[]

A buffer that the developer can use to put data to be transmitted over the socket. It is of size HTTP_MAXBUFFER (defaults to 256 bytes). Pointer into the buffer given above. This should be treated as read-only. It holds the method by which the web request was submitted. The value is either HTTP_METHOD_GET or HTTP_METHOD_POST, for the GET and POST request methods, respectively. This should be treated as read-only. It holds the URL by which the current web request was submitted. . If there is GET-style form information, then that information will follow the first NULL byte in the url array. The form information will itself be NULL-terminated. If the information in the url array is truncated to HTTP_MAXURL bytes, the truncated information is also NULL-terminated. This should be treated as read-only. This holds the version of the HTTP request that was made. It can be HTTP_VER_09, HTTP_VER_10, or HTTP_VER_11 for 0.9, 1.0, or 1.1 requests, respectively. This should be treated as read-only. This buffer holds the value from the Content-Type header sent by the client. This should be treated as read-only. This variable holds the length of the content sent by the client. It matches the value of the ContentLength header sent by the client. This should be treated as read-only. If the value is 1 there is a GET style form, after the \0 byte in url[]. Set to !0 in user-defined formprolog() function to indicate that the formepilog() function needs to be called on an abort condition. If the epilog function is reached normally, this field must be set to zero. This prevents the formepilog function from being called one more time on a connection abort. This should be treated as read-only. It is intended for when the userdefined functions, which may be called before and after an HTML form is submitted, are used for locking resources. If the formprolog function was called and then the connection is aborted before the formepilog function can be called, cancel is set to 1 and the formepilog function is called exactly once. If the epilog function was already called but returned zero (not finished yet), then it is called again if the connection is aborted, except if cgi_redirectto() has been called from the epilog function. In that case the epilog function is not called after an abort.

p method

url[]

version

content_type[]

content_length

has_form
abort_notify

cancel

username[]

Read-only buffer has username of the user making the request, if authentication took place.
TCP/IP Users Manual

300

password[]

Read-only buffer has password of the user making the request, if authentication took place. Read-only buffer contains the value of the cookie "DCRABBIT" (see http_setcookie() for more information). These variables can be used together to cause the web server to flush data from the buffer[] array in the HttpState structure. headerlen should be set to the amount of data in buffer[], and headeroff should be set to 0 (to indicate the offset into the array). The next time the CGI function is called the data in buffer[] will be flushed to the socket. Support for conditional SSI (error feedback etc.). This field is included if HTTP_USERDATA_SIZE is defined. It is an optional user data area. The area is cleared to zero when the structure is initialized, otherwise it is not touched. Its size must be greater than zero.

cookie[]

headerlen headeroff

cond[] userdata[]

9.2 Configuration Macros


The following macros are available in HTTP.LIB:

HTTP_DIGEST_NONCE_TIMEOUT
This macro is used when USE_HTTP_DIGEST_AUTHENTICATION is set to one. Nonces that are generated by the server are valid for this many seconds (900 by default). If set to 0, nonces are good forever. Setting this to a smaller value can possibly result in higher security, although internal use of the nonce-count facility offsets this. Setting it to a larger value reduces the negotiation between the browser and the server, since when a nonce times out, the browser must be told that it is using a stale nonce value and provided with a new one. Since Mozilla and Netscape ignore the stale parameter, the user must reenter the username and password when a nonce times out. Internet Explorer and Opera respect the stale parameter, so they automatically try the username and password with the new nonce without asking the user.

HTTP_MAXBUFFER
This is the size of the buffer accessible through the HttpSpec structure. It defaults to 256 bytes. The size of this buffer affects the speed of the HTTP server; the larger the buffer (up to a point), the faster the server will run. The buffer size is also important for use in CGI functions because it is a work space the users can use. HTTP_MAXBUFFER must be at least 180 bytes for CGI functionality.

HTTP_MAX_COND
Support for conditional SSI (error feedback etc.). It defaults to 4.

Chapter 9: HTTP Server

301

HTTP_MAXNAME
This is the maximum length for a name in the HttpSpec structure. This defaults to 20 characters. Without overriding this value, the maximum length of any name is 19 characters because one character is used for the NULL termination.

HTTP_MAX_NONCES
This macro is used when USE_HTTP_DIGEST_AUTHENTICATION is set to one. Defined to 5 by default, it specifies the number of nonces the HTTP server will allow as valid at any one time. This value should be somewhat larger than the maximum number of clients expected to be accessing the server simultaneously. Otherwise performance could suffer as clients are forced to retry authorization in order to acquire a fresh nonce.

HTTP_MAXSERVERS
This is the maximum number of HTTP servers listening on port 80. The default is two. You may increase this value to the maximum number of independent entities on your page. For example, for a Web page with four pictures, two of which are the same, set HTTP_MAXSERVERS to four: one for the page, one for the duplicate images, and one for each of the other two images. By default, each server takes 2500 bytes of RAM. This RAM usage can be changed by the macro SOCK_BUF_SIZE (or tcp_MaxBufSize which is deprecated as of Dynamic C ver. 6.57). Another option is to use the tcp_reserveport() function and a smaller number of sockets.

HTTP_MAXURL
This macro defines the maximum incoming URL. This could be important if someone is allowing GET requests with a large number of parameters.

HTTP_NO_FLASHSPEC
When defined, this macro saves space by not compiling in code that supports the HttpSpec structure. Presumably the application is using the zserver library to add entries to the HTTP server.

HTTP_PORT
This macro allows the user to override the default port of 80. Define it before the line #use http.lib.

HTTP_TIMEOUT
Defines the number of seconds of no activity that can elapse before the HTTP server closes a connection. The default is 16 seconds.

302

TCP/IP Users Manual

HTTP_USERDATA_SIZE
This macro causes "char userdata[]" to be added to the HttpState structure. Define your structure before the statement #use HTTP.LIB. struct UserStateData {char name[50]; int floor; int model;}; #define HTTP_USERDATA_SIZE (sizeof(struct UserStateData)) #use http.lib In your own code, access it like: mystate = (struct UserStateData *) state->userdata;

TIMEZONE
This macro specifies the distance in hours you are from Coordinated Universal Time (UTC), which is 5 hours ahead of Eastern Standard Time (EST). The default TIMEZONE is -8, which represents Pacific Standard Time. You can use the tm_wr()function to set the clock to the correct value. If you lose power and dont have the batterybackup option, the time will need to be reset.

USE_HTTP_DIGEST_AUTHENTICATION
Set to 1 to enable digest authentication, 0 to disable digest authentication. Set to 0 by default.

USE_HTTP_BASIC_AUTHENTICATION
Set to 1 to enable basic authentication, 0 to disable basic authentication. Set to 1 by default.

9.2.1 Customizing HTTP headers


The callback macro, HTTP_CUSTOM_HEADERS, will be called whenever HTTP headers are being sent. It must be defined as a function with the following prototype: void my_headers(HttpState *state, char *buffer, int bytes); state buffer bytes Pointer to the state structure for the calling web server. The buffer in which the header(s) can be written. The number of bytes available in the buffer.

Chapter 9: HTTP Server

303

Typically, the macro would be defined by the user before http.lib is used, like in the following: #define HTTP_CUSTOM_HEADERS(state, buffer, bytes) \ my_headers(state, buffer, bytes) Then, for the above to work, my_headers() must be defined by the user, like so: void my_headers(HttpState *state, char *buffer, int bytes) { strcpy(buffer, "Fake-Header: Hello Z-World!\r\n"); printf("bytes: %d\n", bytes); } In the real world, the user may need to check the number of bytes available to be sure they don't overwrite the buffer. The buffer must end with "\r\n" and be NULL-terminated.

9.3 File Compression Support


Dynamic C 8 introduces file compression support with the HTTP server. The sample program /SAMPLES/TCPIP/HTTP/ZIMPORT.C demonstrates how to use this functionality. In the sample program, notice that the statement use zimport.lib comes before the statement use http.lib in the code. This is required to have file compression support in the web server. The next thing to notice is the use of the compiler directive #zimport instead of #ximport. #zimport performs a standard #ximport, but compresses the file by invoking a compression utility before emitting the file to the target. There are 2 structures that give web servers access to files: http_flashspec[] and server_spec[]. Compressed files entered into the http_flashspec array are recognized by the server automatically. However,compressed files added to the server spec list must have the macro SERVER_COMPRESSED ORed with the servermask value in the function calls sspec_adxmemfile() or sspec_addfsfile(). For example if you add the file alice.html, like this: sspec_addxmemfile("/alice.html", alice_html, SERVER_HTTP | SERVER_COMPRESSED); when the page is served it will be decompressed on-the-fly. If SERVER_COMPRESSED is not included in the servermask value, then the file will be sent in its compressed form instead. Each instance of the HTTP server will use a buffer for decompressionthis is necessary since multiple server instances can be decompressing files at the same time. Make sure that the buffer macro INPUT_COMPRESSION_BUFFER is at least as large as HTTP_MAXSERVERS. The buffer macro describes the number of 4KB RAM buffers used for decompression. For details on compression ratios, memory usage and performance, please see Technical Note 234, File Compression. For more information on using #zimport and the support libraries, please see the Dynamic C Users Manual and the Dynamic C Function Reference Manual. All of these documents are available on our website, at www.zworld.com.

304

TCP/IP Users Manual

9.4 Sample Programs


Sample programs demonstrating HTTP are in the Samples\Tcpip\Http directory. There is a configuration block at the beginning of each sample program. Unless you are using BOOTP/DHCP, the macros in this block need to be changed to reflect your network settings. For most HTTP programs, you will be concerned with TIMEZONE and the IP address macros, MY_IPADDRESS, MY_NETMASK and MY_GATEWAY. Starting with Dynamic C 7.30, setting up the network addresses is both more complex and more simple. The complexity lies in the added support for multiple interfaces. Luckily for us, the simplicity is in the interface to this more intricate implementation. In the file tcp_config.lib are predefined configurations that may be accessed by a #define of the macro TCPCONFIG. The old way of setting up the addresses has been commented out in the following program, static.c. For instructions on how to set the configuration, please see Section 2.2.2 or LIB\TCPIP\TCP_CONFIG.LIB.

Chapter 9: HTTP Server

305

9.4.1 Serving Static Web Pages


The sample program, Static.c, initializes HTTP.LIB and then sets up a basic static web page. It is assumed you are on the same subnet as the controller. The code for Static.c is explained in the following pages. From Dynamic C, compile and run the program. You will see the LNK light on the board come on after a couple of seconds. Point your internet browser at the controller (e.g., http://10.10.6.100/). The ACT light will flash a couple of times and your browser will display the page.

Program Name: Static.c


// #define MY_IP_ADDRESS "10.10.6.100" // #define MY_NETMASK "255.255.255.0" // #define TIMEZONE -8 #define TCPCONFIG 1 #memmap xmem #use "dcrtcp.lib" #use "http.lib" #ximport "samples/tcpip/http/pages/static.html" index_html #ximport "samples/tcpip/http/pages/rabbit1.gif" rabbit1_gif const HttpType http_types[] = { { ".html", "text/html", NULL}, { ".gif", "image/gif", NULL} }; const HttpSpec http_flashspec[] = { {HTTPSPEC_FILE, "/", index_html, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE, "/index.html", index_html, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE, "/rabbit1.gif", rabbit1_gif, NULL,0,NULL, NULL}, }; main() { sock_init(); // Initializes the TCP/IP stack http_init(); // Initializes the web server tcp_reserveport(80); while (1) { http_handler(); } }

This program serves the static.html file and the rabbit1.gif file to any user contacting the controller. If you want to change the file that is served by the controller, modify this line in Static.c: #ximport "samples/tcpip/http/pages/static.html" index_html Replace static.html with the name of the file you want the controller to serve.

306

TCP/IP Users Manual

9.4.1.1 Adding Files to Display


Adding additional files to the controller to serve as web pages is slightly more complicated. First, add an #ximport line with the filename as the first parameter, and a symbol that references it in Dynamic C as the second parameter. #ximport "samples/tcpip/http/pages/static.html" index_html #ximport "samples/tcpip/http/pages/newfile.html" newfile_html Next, find these lines in Static.c:
HttpSpec http_flashspec[] = { {HTTPSPEC_FILE, "/", index_html, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE, "/index.html", index_html,NULL,0,NULL,NULL}, {HTTPSPEC_FILE, "/rabbit1.gif", rabbit1_gif,NULL,0,NULL,NULL}, };

Insert the name of your new file, preceded by /, into this structure, using the same format as the other lines.
HttpSpec http_flashspec[] = { {HTTPSPEC_FILE, "/", index_html, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE, "/index.html", index_html,NULL,0,NULL, NULL}, {HTTPSPEC_FILE, "/newfile.html", index_html,NULL,0,NULL,NULL}, {HTTPSPEC_FILE, "/rabbit1.gif", rabbit1_gif,NULL,0,NULL,NULL}, };

Compile and run the program. Open up your browser to the new page (e.g., http://10.10.6.100/newfile.html), and your new page will be displayed by the browser.

9.4.1.2 Adding Files with Different Extensions


If you are adding a file with an extension that is not html or gif, you will need to make an entry in the HttpType structure for the new extension. The first field is the extension and the second field describes the MIME type for that extension. You can find a list of MIME types at: ftp://ftp.isi.edu/in-notes/iana/assignments/media-types/mediatypes In the media-types document located there, the text in the type column would precede the /, and the subtype column would directly follow. Find the type subtype entry that matches your extension and add it to the http_types table.
HttpType http_types[] = { { ".html", "text/html", NULL}, { ".gif", "image/gif", NULL} };

Chapter 9: HTTP Server

307

9.4.1.3 Handling of Files With No Extension


The entry / and files without an extension are dealt with by the handler specified in the first entry in http_types[]. If NULL is passed in for the handler, the default handler is used. It passes the information verbatim.

9.4.2 Dynamic Web Pages Without HTML Forms


Serving a dynamic web page without the use of HTML forms is done by sample program ssi.c. This program displays four lights and four buttons to toggle them. Users can browse to the device and change the status of the lights.

Program Name: Samples\tcpip\http\ssi.c


#define MY_GATEWAY "10.10.6.19" #define MY_IP_ADDRESS "10.10.6.100" #define MY_NETMASK "255.255.255.0" #define SOCK_BUF_SIZE 2048 #define HTTP_MAXSERVERS 1 #define MAX_SOCKETS 1 #define REDIRECTHOST MY_IP_ADDRESS #define REDIRECTTO "http: //" REDIRECTHOST "/index.shtml" #memmap xmem #use "dcrtcp.lib" #use "http.lib" /* The source code for this program is ximported. This allows us to put the line * <!--#include file="ssi.c" --> in the file * Samples/Tcpip/Http/Pages/Showsrc.shtml.*/ #ximport "samples/tcpip/http/pages/ssi.shtml" index_html #ximport "samples/tcpip/http/pages/rabbit1.gif" rabbit1_gif #ximport "samples/tcpip/http/pages/ledon.gif" ledon_gif #ximport "samples/tcpip/http/pages/ledoff.gif" ledoff_gif #ximport "samples/tcpip/http/pages/button.gif" button_gif #ximport "samples/tcpip/http/pages/showsrc.shtml" showsrc_shtml #ximport "samples/tcpip/http/ssi.c" ssi_c /* In this case the extension .shtml is the first type in the type table. * This causes the default (no extension) to assume the shtml_handler. */ const HttpType http_types[] = { { ".shtml", "text/html", shtml_handler}, // ssi { ".html", "text/html", NULL}, // html { ".cgi", "", NULL}, // cgi { ".gif", "image/gif", NULL} }; char led1[15]; char led2[15]; char led3[15]; char led4[15];

308

TCP/IP Users Manual

Program Name: ssi.c (continued)


int led1toggle(HttpState *state) { if (strcmp(led1,"ledon.gif")==0) strcpy(led1,"ledoff.gif"); else strcpy(led1,"ledon.gif"); cgi_redirectto(state,REDIRECTTO); return 0; } int led2toggle(HttpState *state) { if (strcmp(led2,"ledon.gif")==0) strcpy(led2,"ledoff.gif"); else strcpy(led2,"ledon.gif"); cgi_redirectto(state,REDIRECTTO); return 0; } int led3toggle(HttpState *state) { if (strcmp(led3,"ledon.gif")==0) strcpy(led3,"ledoff.gif"); else strcpy(led3,"ledon.gif"); cgi_redirectto(state,REDIRECTTO); return 0; } int led4toggle(HttpState *state) { if (strcmp(led4,"ledon.gif")==0) strcpy(led4,"ledoff.gif"); else strcpy(led4,"ledon.gif"); cgi_redirectto(state,REDIRECTTO); return 0; }

Chapter 9: HTTP Server

309

Program Name: ssi.c (continued)


const HttpSpec http_flashspec[] = { {HTTPSPEC_FILE, "/", index_html, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE, "/index.shtml", index_html,NULL,0,NULL,NULL}, {HTTPSPEC_FILE,"/showsrc.shtml",showsrc_shtml,NULL,0,NULL,NULL}, {HTTPSPEC_FILE,"/rabbit1.gif", rabbit1_gif,NULL,0,NULL,NULL}, {HTTPSPEC_FILE, "/ledon.gif",ledon_gif, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE,"/ledoff.gif",ledoff_gif, NULL, 0, NULL, NULL}, {HTTPSPEC_FILE,"/button.gif",button_gif,NULL, 0, NULL, NULL}, {HTTPSPEC_FILE, "ssi.c", ssi_c, NULL, 0, NULL, NULL}, {HTTPSPEC_VARIABLE, "led1", 0, led1, PTR16, "%s", NULL}, {HTTPSPEC_VARIABLE, "led2", 0, led2, PTR16, "%s", NULL}, {HTTPSPEC_VARIABLE, "led3", 0, led3, PTR16, "%s", NULL}, {HTTPSPEC_VARIABLE, "led4", 0, led4, PTR16, "%s", NULL}, {HTTPSPEC_FUNCTION, "/led1tog.cgi", 0, led1toggle,0,NULL,NULL}, {HTTPSPEC_FUNCTION, "/led2tog.cgi", 0,led2toggle,0,NULL,NULL}, {HTTPSPEC_FUNCTION, "/led3tog.cgi", 0,led3toggle,0,NULL,NULL}, {HTTPSPEC_FUNCTION, "/led4tog.cgi", 0,led4toggle,0,NULL,NULL}, }; main() { strcpy(led1,"ledon.gif"); strcpy(led2,"ledon.gif"); strcpy(led3,"ledoff.gif"); strcpy(led4,"ledon.gif"); sock_init(); http_init(); tcp_reserveport(80); while (1) { http_handler(); } }

When you compile and run ssi.c, you see the LNK light on the board come on. Point your browser at the controller (e.g., http://10.10.6.100/). The ACT light will flash a couple of times and your browser will display the page. This program displays pictures of LEDs. Their state is toggled by pressing the image of a button. This program uses Server Side Includes (SSI) and the Common Gateway Interface (CGI).

310

TCP/IP Users Manual

9.4.2.1 SSI Feature


SSI commands are an extension of the HTML comment command (<!--This is a comment -->). They allow dynamic changes to HTML files and are resolved at the server side, so the client never sees them. HTML files that need to be parsed because they contain SSI commands, are recognized by the HTTP server by the file extension shtml. The supported SSI commands are: #echo var #exec cmd #include file They are used by inserting the command into an HTML file: <!--#include file=anyfile --> The server replaces the command, #include file, with the contents of anyfile. #exec cmd executes a command and replaces the SSI command with the output.

Dynamically Changing a Variable on a Web Page


The Ssi.shtml file, located in Samples\Tcpip\Http\Pages, gives an example of dynamically changing a variable on a web page using #echo var. <img SRC="<!--#echo var="led1" -->"> In an shtml file, the <!--#echo var="led1" --> is replaced by the value of the variable led1 from the http_flashspec structure. HttpSpec http_flashspec[] = { //... { HTTPSPEC_VARIABLE, "led1", 0, led1, PTR16, "%s", NULL} //... }; shtml_handler looks up led1 and replaces it with the text output from: printf("%s",(char*)led1); The led1 variable is either ledon.gif or ledoff.gif. When the browser loads the page, it replaces <img SRC="<!--#echo var="led1"-->"> with <img SRC="ledon.gif"> or <img SRC="ledoff.gif"> This causes the browser to load the appropriate image file. SSI string variables are only appropriate for relatively short strings. (In the above example, the SSI string variables are ledon.gif and ledoff.gif.) The size that can be output is limited to the
Chapter 9: HTTP Server 311

size HTTP_MAXBUFFER. If you need larger strings, you should either increase HTTP_MAXBUFFER (which will use more root RAM) or switch to using a CGI function.

9.4.2.2 CGI Feature


Ssi.c also demonstrates the Common Gateway Interface. CGI is a standard for interfacing external applications with HTTP servers. Each time a client requests an URL corresponding to a CGI program, the server will execute the CGI program in real-time. For increased flexibility, a CGI function is responsible for outputting its own HTTP headers. Information about HTTP headers can be found at: http://deesse.univ-lemans.fr:8003/Connected/RFC/1945/ In the Ssi.shtml file, this line creates the clickable button viewable from the browser. <TD> <A HREF="/led1tog.cgi"> <img SRC="button.gif"> </A> </TD> When the user clicks on the button, the browser will request the /led1tog.cgi entity. This causes the HTTP server to examine the contents of the http_flashspec structure looking for /led1tog.cgi. It finds it and notices that led1toggle() needs to be called. The led1toggle function changes the value of the led1 variable, then redirects the browser back to the original page. When the original page is reloaded by the browser, the LED image will have changed states to reflect the users action. 9.4.2.2.1 Connection Abort Condition There are two fields in the HttpState structure that allow a CGI function to appropriately respond to a connection abort condition. The user may set the field abort_notify to a nonzero value in a CGI function to request that the CGI function be called one more time with the cancel field set to one if a connection abort occurs.

9.4.3 Web Pages With HTML Forms


With a web browser, HTML forms enable users to input values. With a CGI program, those values can be sent back to the server and processed. The FORM and INPUT tags are used to create forms in HTML. The FORM tag specifies which elements constitute a single form and what CGI program to call when the form is submitted. The FORM tag has an option called ACTION. This option defines what CGI program is called when the form is submitted (when the Submit button is pressed). The FORM tag also has an option called METHOD that defines the method used to return the form information to the web server. In Section 9.4.3.1, Sample HTML Page, on page 313, the POST method is used, which will be described later. All of the HTML between the <FORM> and </FORM> tags define what is contained within a form. The INPUT tag defines a specific form element, the individual input fields in a form. For example, a text box in which the user may type in a value, or a pull-down menu from which the user may choose an item. The TYPE parameter defines what type of input field is being used. In the following example, in the first two cases , it is the text input field, which is a single-line text entry box. The NAME parameter defines what the name of that particular input variable is, so that when the information is returned to the server, then the server can associate it with a particular variable. The
312 TCP/IP Users Manual

VALUE parameter defines the current value of the parameter. The SIZE parameter defines how long the text entry box is (in characters). At the end of the HTML page in our example, the Submit and Reset buttons are defined with the INPUT tag. These use the special types submit and reset, since these buttons have special purposes. When the submit button is pressed, the form is submitted by calling the CGI program myform.

9.4.3.1 Sample HTML Page


An HTML page that includes a form may look like the following: <HTML> <HEAD><TITLE>ACME Thermostat Settings</TITLE></HEAD> <BODY> <H1>ACME Thermostat Settings</H1> <FORM ACTION="myform.html" METHOD="POST"> <TABLE BORDER> <TR> <TD>Name</TD> <TD>Value</TD> <TD>Description</TD> </TR> <TR> <TD>High Temp</TD> <TD><INPUT TYPE="text" NAME="temphi" VALUE="80" SIZE="5"> </TD> <TD>Maximum in temperature range (&deg;F)</TD> </TR> <TR> <TD>Low Temp</TD> <TD><INPUT TYPE="text" NAME="templo" VALUE="65" SIZE="5"> </TD> <TD>Minimum in temperature range (&deg;F)</TD> </TR> </TABLE> <P> <INPUT TYPE="submit" VALUE="Submit"> <INPUT TYPE="reset" Value="Reset"> </FORM></BODY> </HTML>

Chapter 9: HTTP Server

313

The form might display as follows:

When the form is displayed by a browser, the user can change values in the form. But how does this changed data get back to the HTTP server? By using the HTTP POST command. When the user presses the Submit button, the browser connects to the HTTP server and makes the following request: POST myform HTTP/1.0 . . (some header information) . Content-Length: 19 where myform is the CGI program that was specified in the ACTION attribute of the FORM tag and POST is the METHOD attribute of the FORM tag. Content-Length defines how many bytes of information are being sent to the server (not including the request line and the headers). Then, the browser sends a blank line followed by the form information in the following manner: temphi=80&templo=65 That is, it sends back name and value pairs, separated by the & character. (There can be some further encoding done here to represent special characters, but we will ignore that in this explanation.) The server must read in the information, decode it, parse it, and then handle it in some fashion. It will check the validity of the new values, and then assign them to the appropriate C variable if they are valid.

314

TCP/IP Users Manual

9.4.3.2 POST-Style Form Submission


If an HTML file specifies a POST-style form submission (i.e., METHOD="POST"), the form will still be waiting on the socket when the CGI handler is called. Therefore, it is the job of the CGI handler to read this data off the socket and parse it in a meaningful way. The sample files Post.c and Post2.c in the \Samples\Tcpip\Http folder show how to do this. The HTTP POST command can put any kind of data onto the network. There are many known encoding schemes currently used, but we will only look at URL-encoded data in this document. Other encoding schemes can be handled in a similar manner.

9.4.3.3 URL-Encoded Data


URL-encoded data is of the form "name1=value1&name2=value2," and is similar to the CGI form submission type passed in normal URLs. This has to be parsed to name=value pairs. The rest of this section details an extensible way to do this. This initializes two possible HTML form entries to be received, and a place to store the results. #define MAX_FORMSIZE 64 typedef struct { char *name; char value[MAX_FORMSIZE]; } FORMType; FORMType FORMSpec[2]; void init_forms(void) { FORMSpec[0].name = "user_name"; FORMSpec[1].name = "user_email"; }

Chapter 9: HTTP Server

315

Reading & Storing URL-encoded Data


parse_post() reads URL-encoded data off the network. and calls parse_token() to store the data in FORMSpec[]. These code snippets are from Samples\tcpip\http\post.c. /* Parse one token 'foo=bar', matching 'foo' to the name field in */ /* the struct, and store 'bar' into the value */ void parse_token(HttpState *state) { int i, len; for(i=0; i<HTTP_MAXBUFFER; i++) { if(state->buffer[i] == '=') state->buffer[i] = '\0'; } state->p = state->buffer + strlen(state->buffer) + 1; for(i=0; i<(sizeof(FORMSpec)/sizeof(FORMType)); i++) { if(!strcmp(FORMSpec[i].name,state->buffer)) { len = (strlen(state->p)>MAX_FORMSIZE) ? MAX_FORMSIZE 1: strlen(state->p); strncpy(FORMSpec[i].value,state->p,1+len); FORMSpec[i].value[MAX_FORMSIZE - 1] = '\0'; } } }

316

TCP/IP Users Manual

/* Parse the url-encoded POST data into FORMSpec structure */ /* e.g., parse 'foo=bar&baz=qux' into the struct) */ int parse_post(HttpState *state) { auto int retval; while(1) { retval = sock_fastread(&state->s, state->p, 1); if(0 == retval) { *state->p = '\0'; parse_token(state); return 1 } /* should this only be '&'? (allow the eoln as valid text?) */ if((*state->p == '&') || (*state->p == '\r') || (*state->p == '\n')) { /* found one token */ *state->p = '\0'; parse_token(state); state->p = state->buffer; } else { state->p++; } if((state->p - state->buffer) > HTTP_MAXBUFFER) return 1; // input too long } return 0; // end of data - loop again to give it time to write more }

9.4.3.4 Sample of a CGI Handler


This next function is the CGI handler. It is a state machine-based handler that generates the page. It calls parse_post() and references the structure that is now filled with the parsed data we wanted.

Chapter 9: HTTP Server

317

This function is from Samples\tcpip\http\post.c. int submit(HttpState *state){ auto int i; if(state->length) { // buffer to write out if(state->offset < state->length) { state->offset += sock_fastwrite(&state->s, state>buffer + (int)state->offset,(int)state->length (int)state -> offset); } else { state->offset = 0; state->length = 0; } } else { switch(state->substate) { case 0: strcpy(state->buffer, "HTTP/1.0 200 OK\r\n\r\n"); state->length = strlen(state->buffer); state->offset = 0; state->substate++; break; case 1: strcpy(state>buffer,"<html><head><title>Results</title> </head><body>\r\n"); state->length = strlen(state->buffer); state->substate++; break; case 2: // init the FORMSpec data FORMSpec[0].value[0] = '\0'; FORMSpec[1].value[0] = '\0'; state->p = state->buffer; state->substate++; break; case 3: // parse the POST information if(parse_post(state)) { sprintf(state->buffer, "<p>Username: %s<p>\r\n<p>Email: %s<p>\r\n", FORMSpec[0].value, FORMSpec[1].value); state->length = strlen(state->buffer); state->substate++; } break;

318

TCP/IP Users Manual

case 4: strcpy(state->buffer,"<p>Go <a href=\"/\">home</a></body> </html>\r\n"); state->length = strlen(state->buffer); state->substate++; break; default: state->substate = 0; return 1; } } return 0; }

Chapter 9: HTTP Server

319

9.4.4 HTML Forms Using Zserver.lib


In this section, we will step through an example program, Samples\tcpip\http\form1.c, that uses HTML forms. Through this step-by-step explanation, the method of using the functions in zserver.lib will become clear. These lines are part of the standard TCP/IP configuration prior to Dynamic C 7.30. You must change them to whatever your local IP address and netmask are. Contact your network administrator for these numbers. #define MY_IP_ADDRESS #define MY_NETMASK "10.10.6.112" "255.255.255.0"

Defining FORM_ERROR_BUF is required in order to use the HTML form functionality in Zserver.lib. The value represents the number of bytes that will be reserved in root memory for the buffer which will be used for form processing. This buffer must be large enough to hold the name and value for each variable, plus four bytes for each variable. Since we are building a small form, 256 bytes is sufficient. #define FORM_ERROR_BUF 256 Since we will not be using the http_flashspec array, we can define the following macro, to remove some code for handling this array from the web server. #define HTTP_NO_FLASHSPEC These lines are part of the standard TCP/IP configuration. #memmap xmem #use "dcrtcp.lib" #use "http.lib" const HttpType http_types[] = { { ".html", "text/html", NULL} }; These are the declarations of the variables that will be included in the form. int temphi; int tempnow; int templo; float humidity; char fail[21];

320

TCP/IP Users Manual

void main(void) { An array of type FormVar must be declared to hold information about the form variables. Be sure to allocate enough entries in the array to hold all of the variables that will go in the form. If more forms are needed, then more of these arrays can be allocated. FormVar myform[5]; These variables will hold the indices in the TCP/IP servers object list for the form and the form variables. int var; int form; This array holds the possible values for the fail variable. The fail variable will be used to make a pulldown menu in the HTML form. const char *const fail_options[] = { "Email", "Page", "Email and page", "Nothing" }; These lines initialize the form variables. temphi = 80; tempnow = 72; templo = 65; humidity = 0.3; strcpy(fail, "Page"); The next line adds a form to the TCP/IP servers object list. The first parameter gives the name of the form. Hence, when a browser requests the page myform.html, the HTML form is generated and presented to the browser. The second parameter gives the developer-declared array in which form information will be saved. The third parameter gives the number of entries in the myform array (this number should match the one given in the myform declaration above). The fourth parameter indicates that this form should only be accessible to the HTTP server, and not the FTP server. SERVER_HTTP should always be given for HTML forms. The return value is the index of the newly created form in the TCP/IP servers object list. form = sspec_addform("myform.html", myform, 5, SERVER_HTTP);

Chapter 9: HTTP Server

321

This line sets the title of the form. The first parameter is the form index ( the return value of sspec_addform()), and the second parameter is the form title. This title will be displayed as the title of the HTML page and as a large heading in the HTML page. sspec_setformtitle(form, "ACME Thermostat Settings"); The following line adds a variable to the TCP/IP servers object list. It must be added to the TCP/IP servers object list before being added to the form. The first parameter is the name to be given to the variable, the second is the address of the variable, the third is the type of variable (this can be INT8, INT16, INT32, FLOAT32, or PTR16), the fourth is a printf-style format specifier that indicates how the variable should be printed, and the fifth is the server for which this variable is accessible. The return value is the index of the variable in the TCP/IP servers object list. var = sspec_addvariable("temphi", &temphi, INT16, "%d", SERVER_HTTP); The following line adds a variable to a form. The first parameter is the index of the form to add the variable to ( the return value of sspec_addform()), and the second parameter is the index of the variable ( the return value of sspec_addvariable()). The return value is the index of the variable within the developer-declared FormVar array, myform. var = sspec_addfv(form, var); This function sets the name of a form variable that will be displayed in the first column of the form table. If this name is not set, it defaults to the name for the variable in the TCP/IP servers object list (temphi, in this case). The first parameter is the form in which the variable is located, the second parameter is the variable index within the form, and the third parameter is the name for the form variable. sspec_setfvname(form, var, "High Temp"); This function sets the description of the form variable, which is displayed in the third column of the form table. sspec_setfvdesc(form, var, "Maximum in temperature range (60 - 90 &deg;F)"); This function sets the length of the string representation of the form variable. In this case, the text box for the form variable in the HTML form will be 5 characters long. If the user enters a value longer than 5 characters, the extra characters will be ignored. sspec_setfvlen(form, var, 5);

322

TCP/IP Users Manual

This function sets the range of values for the given form variable. The variable must be within the range of 60 to 90, inclusive, or an error will be generated when the form is submitted. sspec_setfvrange(form, var, 60, 90); This concludes setting up the first variable. The next five lines set up the second variable, which represents the current temperature. var = sspec_addvariable("tempnow", &tempnow, INT16, "%d",SERVER_HTTP); var = sspec_addfv(form, var); sspec_setfvname(form, var, "Current Temp"); sspec_setfvdesc(form, var, "Current temperature in &deg;F"); sspec_setfvlen(form, var, 5); Since the value of the second variable should not be modifiable via the HTML form (by default variables are modifiable,) the following line is necessary and makes the given form variable readonly when the third parameter is 1. The variable will be displayed in the form table, but can not be modified within the form. sspec_setfvreadonly(form, var, 1); These lines set up the low temperature variable. It is set up in much the same way as the high temperature variable. var = sspec_addvariable("templo", &templo, INT16, "%d", SERVER_HTTP); var = sspec_addfv(form, var); sspec_setfvname(form, var, "Low Temp"); sspec_setfvdesc(form, var, "Minimum in temperature range (50 - 80 &deg;F)"); sspec_setfvlen(form, var, 5); sspec_setfvrange(form, var, 50, 80); This code begins setting up the string variable that specifies what to do in case of air conditioning failure. Note that the variable is of type PTR16, and that the address of the variable is not given to sspec_addvariable(), since the variable fail already represents an address. var = sspec_addvariable("failure", fail, PTR16, "%s", SERVER_HTTP); var = sspec_addfv(form, var); sspec_setfvname(form, var, "Failure Action"); sspec_setfvdesc(form, var, "Action to take in case of airconditioning failure"); sspec_setfvlen(form, var, 20);

Chapter 9: HTTP Server

323

This line associates an option list with a form variable. The third parameter gives the developerdefined option array, and the fourth parameter gives the length of the array. The form variable can now only take on values listed in the option list. sspec_setfvoptlist(form, var, fail_options, 4); This function sets the type of form element that is used to represent the variable. The default is HTML_FORM_TEXT, which is a standard text entry box. This line sets the type to HTML_FORM_PULLDOWN, which is a pull-down menu. sspec_setfventrytype(form, var, HTML_FORM_PULLDOWN); Finally, this code sets up the last variable. Note that it is a float, so FLOAT32 is given in the sspec_addvariable() call. The last function call is sspec_setfvfloatrange() instead of sspec_setfvrange(), since this is a floating point variable. var = sspec_addvariable("humidity", &humidity, FLOAT32, "%.2f", SERVER_HTTP); var = sspec_addfv(form, var); sspec_setfvname(form, var, "Humidity"); sspec_setfvdesc(form, var, "Target humidity (between 0.0 and 1.0)"); sspec_setfvlen(form, var, 8); sspec_setfvfloatrange(form, var, 0.0, 1.0); These calls create aliases in the TCP/IP servers object list for the HTML form. That is, the same form can now be generated by requesting index.html or /. Note that sspec_aliasspec() should be called after the form has already been set up. The aliasing is done by creating a new entry in the TCP/IP servers object list and copying the original entry into the new entry. Note that aliasing can also be done for files and other types of server objects. sspec_aliasspec(form, "index.html"); sspec_aliasspec(form, "/"); These lines complete the sample program. They initialize the TCP/IP stack and web server, and run the web server. sock_init(); http_init(); while (1) { http_handler(); } }

324

TCP/IP Users Manual

This is the form that is generated:

Chapter 9: HTTP Server

325

9.5 API Functions cgi_redirectto


void cgi_redirectto( HttpState *state, char *url );
DESCRIPTION

This utility function may be called in a CGI function to redirect the user to another page. It sends a user to the URL stored in url. You should immediately issue a return 0; after calling this function. The CGI is considered finished when you call this, and will be in an undefined state. The http samples work correctly with cgi_redirectto() because they use macro constants to define the url parameter. If you manipulate the url string, please be aware of the following issues:

The library function sets a pointer to the 2nd parameter - url. The calling routine is
responsible for ensuring that the location represented by the pointer remains valid after the call. This is because the url string will not be processed until after the cgi function is finished.

If the application has MAX_TCP_SOCKET_BUFFERS and


HTTP_MAXSERVERS set to more than one, it is possible that the cgi function will be called successively with different server states serving different client requests. In these circumstances it is necessary to ensure that the pointer to the url is valid for each of the server states.

After the cgi function has called cgi_redirecto() and returns 0, the
http_handler then causes the server response to be sent to the browser. The information is sent as follows: 1. HTTP header response containing the redirection information response code 302. 2. A human readable redirection html page telling the user that redirection has taken place, and to click "here" to go to the new URL. This is for browsers which do not recognise the rediction 302 command in the header. This may cause a problem for browsers which do recognise the 302 redirection command. Some browsers immediately issue a GET request to the new location while still reading in the human readable page. If MAX_TCP_SOCKET_BUFFERS and HTTP_MAXSERVERS are set to one, the server will not receive the GET request because it is busy sending out the the human-readable page. The symptom is that the browser appears to time-out. (This timing problem may be masked when a proxy server is used.) Set MAX_TCP_SOCKET_BUFFERS and HTTP_MAXSERVERS to a value more than one to prevent this problem.

326

TCP/IP Users Manual

PARAMETERS

state url
RETURN VALUE

Current server struct, as received by the CGI function. Fully qualified URL to redirect to.

None - sets the state, so the CGI must immediately return with a value of 0.
LIBRARY

HTTP.LIB
SEE ALSO

cgi_sendstring

cgi_sendstring
void cgi_sendstring( HttpState *state, char *str );
DESCRIPTION

Sends a string to the user. You should immediately issue a return 0; after calling this function. The CGI is considered finished when you call this, and will be in an undefined state. This function greatly simplifies a CGI handler because it allows you to generate your page in a buffer, and then let the library handle writing it to the network.
PARAMETERS

state str
RETURN VALUE

Current server struct, as received by the CGI function. String to send.

None - sets the state, so the CGI must immediately return with a value of 0.
LIBRARY

HTTP.LIB
SEE ALSO

cgi_redirectto

Chapter 9: HTTP Server

327

http_addfile
int http_addfile( char *name, long location );
DESCRIPTION

Adds a file to the TCP/IP servers object list.


PARAMETERS

name location
RETURN VALUE

Name of the file (e.g., "/index.html"). Address of the file data. (from #ximport)

0: Success. 1: Failure.
LIBRARY

HTTP.LIB
SEE ALSO

http_delfile

328

TCP/IP Users Manual

http_contentencode
char *http_contentencode( char *dest, const char *src, int len );
DESCRIPTION

Converts a string to include HTTP transfer-coding ''tokens'' (such as &#64; (decimal) for at-sign) where appropriate. Encodes these characters: ''<>@%#&'' Source string is NULL-byte terminated. Destination buffer is bounded by len. This function is reentrant.
PARAMETERS

dest src len


RETURN VALUE

Buffer where encoded string is stored. Buffer holding original string (not changed) Size of destination buffer.

dest: There was room for all conversions. NULL: Not enough room.
LIBRARY

HTTP.LIB
SEE ALSO

http_urldecode

Chapter 9: HTTP Server

329

http_date_str
char *http_date_str( char *buf );
DESCRIPTION

Print the date (time zone adjusted) into the given buffer. This assumes there is room!
PARAMETERS

buf
RETURN VALUE

The buffer to write the date into. This requires at least 30 bytes in the destination buffer.

A pointer to the string.


LIBRARY

HTTP.LIB
SEE ALSO

http_handler

http_delfile
int http_delfile( char *name );
DESCRIPTION

Deletes a file from TCP/IP servers object list.


PARAMETERS

name
RETURN VALUE

Name of the file, as passed to http_addfile.

0: Success; 1: Failure (not found).


LIBRARY

HTTP.LIB
SEE ALSO

http_addfile

330

TCP/IP Users Manual

http_finderrbuf
char *http_finderrbuf( char *name );
DESCRIPTION

Finds the occurrence of the given variable in the HTML form error buffer, and returns its location.
PARAMETERS

name
RETURN VALUE

Name of the variable.

NULL: Failure. !NULL: Success, location of the variable in the error buffer.
LIBRARY

HTTP.LIB

http_findname
HttpSpecAll http_findname( char *name );
DESCRIPTION

Finds a spec entry, searching first in RAM, then in flash.


PARAMETERS

name
RETURN VALUE

Name, in text, of the spec to find.

The spec entry.


LIBRARY

HTTP.LIB

Chapter 9: HTTP Server

331

http_handler
void http_handler( void );
DESCRIPTION

This is the basic control function for the HTTP server, a tick function to run the HTTP daemon. It must be called periodically for the daemon to work. It parses the requests and passes control to the other handlers, either html_handler, shtml_handler, or to the developer-defined CGI handler based on the requests extension.
LIBRARY

HTTP.LIB
SEE ALSO

http_init

http_idle
int http_idle( void );
DESCRIPTION

Query to see if any HTTP servers are active.


RETURN VALUE

0: at least one HTTP server is active 1: all HTTP servers are idle
LIBRARY

HTTP.LIB
SEE ALSO

http_handler

332

TCP/IP Users Manual

http_init
int http_init( void );
DESCRIPTION

Initializes the HTTP daemon.


RETURN VALUE

0: Success.
LIBRARY

HTTP.LIB
SEE ALSO

http_handler

http_nextfverr
void http_nextfverr( char *start, char **name, char **value, int *error, char **next );
DESCRIPTION

Gets the information for the next variable in the HTML form error buffer. If any of the last four parameters in the function call are NULL, then those parameters will not have a value returned. This is useful if you are only interested in certain variable information.
PARAMETERS

start

Pointer to the variable in the buffer for which we want to get information. Return location for the name of the variable. Return location for the value of the variable. Return location for whether or not the variable is in error (0 if it is not, 1 if it is). Return location for a pointer to the variable after this one.

name value error

next
RETURN VALUE

None, although information is returned in the last four parameters.


LIBRARY

HTTP.LIB
Chapter 9: HTTP Server 333

http_parseform
int http_parseform( int form, HttpState *state );
DESCRIPTION

Parses the returned form information. It expects a POST submission. This function is useful for a developer who only wants the parsing functionality and wishes to generate forms herself. Note that the developer must still build the array of FormVars and use the server_spec table. This function will not, however, automatically display the form when used by itself. If all variables satisfy all integrity checks, then the variables values are updated. If any variables fail, then none of the values are updated, and error information is written into the error buffer If this function is used directly, the developer must process errors.
PARAMETERS

form

server_spec index of the form (i.e., location in TCP/IP servers object list). The HTTP server with which to parse the POSTed data.

state
RETURN VALUE

0: There is more processing to do; 1: Form processing has been completed.


LIBRARY

HTTP.LIB

334

TCP/IP Users Manual

http_scanpost
int http_scanpost( char *tag, char *buffer, char *dest, int maxlen );
DESCRIPTION

This function allows you to scan a buffer with a POST response for the key/value pairs. This function is reentrant.
PARAMETERS

tag buffer dest maxlen


RETURN VALUE

Buffer holding the tag name. Buffer to read data from. Buffer to store value to. Size of destination buffer.

0: Successful !0: Not successful


LIBRARY

HTTP.LIB

Chapter 9: HTTP Server

335

http_setauthentication
int http_setauthentication(int auth);
DESCRIPTION

Sets the type of authentication to be used globally by the HTTP server. By default, this is set to the strongest available type of authentication available (in order of weakest to strongest: HTTP_NO_AUTH, HTTP_BASIC_AUTH, HTTP_DIGEST_AUTH. This function returns the type of authentication that was actually configured. If the type of authentication that you ask for was not compiled in at compile time, then the type of authentication will not be changed.
PARAMETERS

auth

Type of authentication. Choices are:

HTTP_NO_AUTH HTTP_BASIC_AUTH HTTP_DIGEST_AUTH


RETURN VALUE

Actual resulting type of authentication.


LIBRARY

HTTP.LIB

336

TCP/IP Users Manual

http_setcookie
void http_setcookie( char *buf, char *value );
DESCRIPTION

This utility generates a cookie on the client. This will store the text in value into a cookie-generation header that will be written to buf. The header placed in buf is not automatically sent to the web client. It is the callers responsibility to send the header in buf, along with any other HTTP headers, to the client. When a page is requested from the client, and the cookie is already set, the text of the cookie will be stored in state->cookie[]. This is a char*, and if no cookie was available, state->cookie[0] will equal '\0'.
PARAMETERS

buf

Buffer to store cookie-generation header, i.e., the name of the cookie. Text to store in cookie-generation header, i.e., the value of the cookie.

value

LIBRARY

HTTP.LIB

Chapter 9: HTTP Server

337

http_urldecode
char *http_urldecode( char *dest, const char *src, int len );
DESCRIPTION

Converts a string with URL-escaped ''tokens'' (such as %20 (hex) for space) into actual values. Changes "+" into a space. String can be NULL terminated; it is also bounded by a specified string length. This function is reentrant.
PARAMETERS

dest src len


RETURN VALUE

Buffer where decoded string is stored. Buffer holding original string (not changed). Maximum size of string (NULL terminated strings can be shorter).

dest: if all conversion was good. NULL: if some conversion had trouble.
LIBRARY

HTTP.LIB
SEE ALSO

http_contentencode

338

TCP/IP Users Manual

shtml_addfunction
int shtml_addfunction( char *name, void (*fptr()) );
DESCRIPTION

Adds a CGI/SSI-exec function for making dynamic web pages to the TCP/IP servers object list.
PARAMETERS

name fptr

Name of the function (e.g., "/foo.cgi"). Function pointer to the handler, that must take HttpState* as an argument. This function should return an int (0 while still pending, 1 when finished).

RETURN VALUE

0: Success; 1: Failure (no room).


LIBRARY

HTTP.LIB
SEE ALSO

shtml_delfunction

Chapter 9: HTTP Server

339

shtml_addvariable
int shtml_addvariable( char *name, void *variable, word type, char *format );
DESCRIPTION

This function adds a variable so it can be recognized by shtml_handler().


PARAMETERS

name variable type

Name of the variable. Pointer to the variable. Type of variable. The following types are supported: INT8, INT16, INT32, PTR16, FLOAT32. Standard printf format string. (e.g., "%d").

format
RETURN VALUE

0: Success. 1: Failure (no room).


LIBRARY

HTTP.LIB
SEE ALSO

shtml_delvariable

340

TCP/IP Users Manual

shtml_delfunction
int shtml_delfunction( char *name );
DESCRIPTION

Deletes a function from the TCP/IP servers object list.


PARAMETERS

name
RETURN VALUE

Name of the function as given to shtml_addfunction().

0: Success; 1: Failure (not found).


LIBRARY

HTTP.LIB
SEE ALSO

shtml_addfunction

shtml_delvariable
int shtml_delvariable( char *name );
DESCRIPTION

Deletes a variable from the TCP/IP servers object list.


PARAMETERS

name
RETURN VALUE

Name of the variable, as given to shtml_addvariable().

0: Success; 1: Failure (not found).


LIBRARY

HTTP.LIB
SEE ALSO

shtml_addvariable

Chapter 9: HTTP Server

341

342

TCP/IP Users Manual

10. FTP Client


The library FTP_CLIENT.LIB implements the File Transfer Protocol (FTP) for the client side of the connection. This library supports a single FTP session at any one time since the session state is maintained in a single global structure in root memory. You can upload and download files to either a static buffer in root data memory (for simple applications) or, starting with Dynamic C version 7.20, you can have the data passed to, or generated by, a data handler callback function that you specify. The data handler function can implement large file transfers in extended memory buffers, or it can be used to generate or process data onthe-fly with minimal buffering. Starting with Dynamic C 7.20, you can specify passive mode transfers. This is most important for clients which are inside a firewall. Passive mode is specified by passing the FTP_MODE_PASSIVE option to ftp_client_setup(). When passive mode is specified, the client will actively open the data transfer port to the server, rather than the other way around. This avoids the need for the server to penetrate the firewall with an active connection from the outside, which is most often blocked by the firewall. For this reason, it is recommended that your FTP client application uses passive mode by default, unless overridden by an end-user.

10.1 Configuration Macros


The following macros may be defined in a #define statement before the inclusion of FTP_CLIENT.LIB in an application program. Note that strings must contain the NULL byte, so if a maximum string length is 16, the maximum number of characters is 15.

FTP_MAX_DIRLEN
The default is 64, which is the maximum string length of a directory name.

FTP_MAX_FNLEN
The default is 16, which is the maximum string length of a file name.

FTP_MAX_NAMELEN
The default is 16 which is the maximum string length of usernames and passwords.

FTP_MAXLINE
The default is 256, which is both the maximum command line length and data chunk size that can be passed between the FTP data transfer socket and the data handler (if any defined).

FTP_TIMEOUT
The default is 16, which is the number of seconds that pass before a time out occurs.

Chapter 10: FTP Client

343

10.2 API Functions ftp_client_setup


int ftp_client_setup( long host, int port, char *username, char *password, int mode, char *filename, char *dir, char *buffer, int length );
DESCRIPTION

Sets up a FTP transfer. It is called first, then ftp_client_tick() is called until it returns non-zero. Failure can occur if the host address is zero, if length is negative, or if the internal control socket to the FTP server cannot be opened (e.g., because of lack of socket buffers).
PARAMETERS

host port username password mode

Host IP address of FTP server. Port of FTP server, 0 for default. Username of account on FTP server. Password of account on FTP server. Mode of transfer: FTP_MODE_UPLOAD or FTP_MODE_DOWNLOAD. You may also OR in the value FTP_MODE_PASSIVE to use passive mode transfer (important if you are behind a firewall). Filename to get/put. Directory file is in, NULL for default directory. Buffer to get/put the file from/to. Must be NULL if a data handler function will be used. See ftp_data_handler() for more details. On upload, length of file; on download size of buffer. This parameter limits the transfer size to a maximum of 32767 bytes. For larger transfers, it will be necessary to use a data handler function.

filename dir buffer

length

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

FTP_CLIENT.LIB
SEE ALSO

ftp_client_tick, ftp_data_handler
344 TCP/IP Users Manual

ftp_client_tick
int ftp_client_tick( void );
DESCRIPTION

Tick function to run the FTP daemon. Must be called periodically. The return codes are not very specific. You can call ftp_last_code() to get the integer value of the last FTP message received from the server. See RFC959 for details. For example, code 530 means that the client was not logged in to the server.
RETURN VALUE

FTPC_AGAIN (0): still pending, call again. FTPC_OK (1): success (file transfer complete). FTPC_ERROR (2): failure (call ftp_last_code() for more details). FTPC_NOHOST (3): failure (Couldn't connect to remote host). FTPC_NOBUF (4): failure (no buffer or data handler). FTPC_TIMEOUT (5): warning (Timed out on close: data may or may not be OK). FTPC_DHERROR (6): error (Data handler error in FTPDH_END operation). FTPC_CANCELLED (7): FTP control socket was aborted (reset) by the server.
LIBRARY

FTP_CLIENT.LIB
SEE ALSO

ftp_client_setup, ftp_client_filesize, ftp_client_xfer, ftp_last_code

Chapter 10: FTP Client

345

ftp_client_filesize
int ftp_client_filesize( void );
DESCRIPTION

Returns the byte count of data transferred. This function is deprecated in favor of ftp_client_xfer(), which returns a long value. If the number of bytes transferred was over 32767, then this function returns 32767 which may be misleading.
RETURN VALUE

Size, in bytes.
LIBRARY

FTP_CLIENT.LIB
SEE ALSO

ftp_client_setup, ftp_data_handler, ftp_client_xfer

346

TCP/IP Users Manual

ftp_client_xfer
longword ftp_client_xfer( void );
DESCRIPTION

Returns the byte count of data transferred. Transfers of over 232 bytes (about 4GB) are not reported correctly.
RETURN VALUE

Size, in bytes.
LIBRARY

FTP_CLIENT.LIB
SEE ALSO

ftp_client_setup, ftp_data_handler, ftp_client_filesize

Chapter 10: FTP Client

347

ftp_data_handler
void ftp_data_handler( int (*dhnd)(), void *dhnd_data, word opts );
DESCRIPTION

Sets a data handler for further FTP data transfer(s). This handler is only used if the "buffer" parameter to ftp_client_setup() is passed as NULL. The handler is a function which must be coded according to the following prototype: int my_handler(char *data, int len, longword offset, int flags, void *dhnd_data); This function is called with data pointing to a data buffer, and len containing the length of that buffer. offset is the byte number relative to the first byte of the entire FTP stream. This is useful for data handler functions that do not wish to keep track of the current state of the data source. dhnd_data is the pointer that was passed to ftp_data_handler(). flags contains an indicator of the current operation: FTPDH_IN: data is to be stored on this host (obtained from an FTP download). FTPDH_OUT: data is to be filled with the next data to upload to the FTP server. FTPDH_END: data and len are irrelevant: this marks the end of data, and gives the function an opportunity to e.g., close the file. Called after either in or out processing. FTPDH_ABORT: end of data; error encountered during FTP operation. Similar to END except the transfer did not complete. Can use this to e.g., delete a partially written file. The return value from this function depends on the in/out flag. For FTPDH_IN, the function should return len if the data was processed successfully and download should continue; -1 if an error has occurred and the transfer should be aborted. For FTPDH_OUT, the function should return the actual number of bytes placed in the data buffer, or -1 to abort. If zero is returned, then the upload is terminated normally. For FTPDH_END, the return code should be zero for success or -1 for error. If an error is flagged, then this is used as the return code for ftp_client_tick(). For FTPDH_ABORT, the return code is ignored.

348

TCP/IP Users Manual

ftp_data_handler (continued)
PARAMETERS

dhnd

Pointer to data handler function, or NULL to remove the current data handler. A pointer which is passed to the data handler function. This may be used to point to any further data required by the data handler such as an open file descriptor. Options word (currently reserved, set to zero).

dhnd_data

opts
LIBRARY

FTP_CLIENT.LIB
SEE ALSO

ftp_client_setup

Chapter 10: FTP Client

349

ftp_last_code
int ftp_last_code( void );
DESCRIPTION

Returns the most recent message code sent by the FTP server. RFC959 describes the codes in detail. This function is most useful for error diagnosis in the case that an FTP transfer failed.
RETURN VALUE

Error code; a number between 0 and 999. Codes less than 100 indicate that an internal error occurred e.g., the server was never contacted.
LIBRARY

FTP_CLIENT.LIB
SEE ALSO

ftp_client_setup, ftp_client_tick

350

TCP/IP Users Manual

10.3 Sample FTP Transfer


Program Name: Samples\tcpip\ftp\ftp_client.c
//#define MY_IP_ADDRESS "10.10.6.105" //#define MY_NETMASK "255.255.255.0" #define TCPCONFIG 1 #memmap xmem #use "dcrtcp.lib" #use "ftp_client.lib" #define REMOTE_HOST "10.10.6.19" #define REMOTE_PORT 0 main() { char buf[2048]; int ret, i, j; printf("Calling sock_init()...\n"); sock_init(); /* Set up the ftp transfer. This is to the host defined above, with a normal * anonymous/e-mail password login info. A get of the file bar is requested, which * will be stored in buf.*/ printf("Calling ftp_client_setup()...\n"); if(ftp_client_setup(resolve(REMOTE_HOST), REMOTE_PORT, anonymous", "anon@anon.com", FTP_MODE_DOWNLOAD,"bar", NULL, buf,sizeof(buf))) { printf("FTP setup failed.\n"); exit(0); } printf("Looping on ftp_client_tick()...\n"); while( 0 == (ret = ftp_client_tick()) ) continue; if( 1 == ret ) { printf("FTP completed successfully.\n"); // ftp_client_filesize() returns transfer size,since we asked for download. buf[ftp_client_filesize()] = '\0'; printf("Data => '%s'\n", buf); } else { printf("FTP failed: status == %d\n",ret); } }

Chapter 10: FTP Client

351

352

TCP/IP Users Manual

11. FTP Server


This chapter documents the FTP server. The following information is included:

configuration macros the default file handlers how to assign replacement file handlers what to do when there is a firewall API functions commands accepted by the server reply codes generated by the server sample code demonstrating a working FTP server

The library FTP_SERVER.LIB implements the File Transfer Protocol for the server side of a connection. FTP uses two TCP connections to transfer a file. The FTP server does a passive open on well-known port 21 and then listens for a client. This is the command connection. The server receives commands through this port and sends reply codes. The second TCP connection is for the actual data transfer. Anonymous FTP is supported. Most FTP servers on the Internet use the identifier anonymous. So since FTP clients expect it, this is the identifier that is recommended. But any string (with a maximum length of SAUTH_MAXNAME) may be used. Dynamic C 8 includes some enhancements that basically let the FTP server act as a full FTP server, where you can create, read and delete files at will. To use these enhancements, the configuration macro FTP_USE_FS2_HANDLERS must be defined to enable FS2 support in the default file handler functions. The structure that holds the association of filenames and FS2 file locations is the server spec listthe global array defined in zserver.lib. It is stored in the User block and the API functions ftp_save_filenames() and ftp_load_filenames() are used for support of this. NOTE: For a demonstration of the enhanced FTP server, see the sample program, /SAMPLES/TCPIP/FTP/FTP_SERVER_FULL.C.

Chapter 11: FTP Server

353

11.1 Configuration Macros


The configuration macros control various conditions of the servers operation. Read through them to understand the default conditions. Any changes to these macros may be made in the server application with #define statements before inclusion of FTPSERVER.LIB.

FTP_CMDPORT
This macro defaults to 21 which is the well-known FTP server port number. You can override this to cause the server to listen on a non-standard port number.

FTP_CREATE_MASK
This macro specifies the mask that is passed into the servermask parameter in sspec_addfsfile() calls when a new file is created. In particular, this defines which servers will be allowed to access this file. By default, it is defined to SERVER_FTP | SERVER_WRITABLE .

FTP_DTPTIMEOUT
The default is 16, the same as FTP_TIMEOUT. This applies to the data transfer port instead of the command port. The data transfer port is involved with get/store commands, as well as directory listings.

FTP_EXTENSIONS
The macro is not defined by default. Define it to allow the server to recognize the DELE, SIZE and MDTM commands. If this macro is defined, then the FTP handler structure (FTPhandlers) is augmented with pointers to mdtm and delete handlers.

FTP_INTERFACE
This macro defaults to IF_DEFAULT, i.e., the (single) default interface. Define to IF_ANY if FTP sessions can be accepted on any active interface, or a specific interface number (e.g., IF_ETH0) to allow sessions on that interface only. Note that you are currently limited to a single interface, or all interfaces. This macro is only relevant starting with Dynamic C version 7.30.

FTP_MAXLINE
The default is 256: the number of bytes of the working buffer in each server. This is also the maximum size of each network read/write. The default value of 256 is the minimum value that allows the server to function properly.

FTP_MAXSERVERS
The default is 1: the number of simultaneous connections the FTP server can support. Each server requires a significant amount of RAM (4096 bytes by default, though this can change through SOCK_BUF_SIZE or tcp_MaxBufSize (deprecated)).

FTP_NODEFAULTHANDLERS
This macro is undefined. Define it to eliminate the code for the default file handlers. You must then provide your own file handlers. This macro is no longer needed starting with Dynamic C version 7.20.
354 TCP/IP Users Manual

FTP_TIMEOUT
The default is 16: the number of seconds to wait for FTP commands from the remote host before terminating the connection. In a high-latency network this value may need to be increased to avoid premature closures.

FTP_USE_FS2_HANDLERS
Define this to enable the full use of FS2 in the default FTP handler functions. Defining this macro will automatically define FTP_WRITABLE_FILES to 1, as well.

FTP_USERBLOCK_OFFSET
This macro should be defined to a number that specifies the offset into the User block at which the list of filenames will be saved. This list correlates the filenames with the locations of the files in the filesystem (FS2). This macro defaults to 0. If the user is putting other information in the User block, this offset may need to be adjusted to prevent clobbering the other data.

FTP_WRITABLE_FILES
The defaults is 0. Define to 1 to provide support in ftp_dflt_open() for authenticating a user for write access before a file is opened. This also provides support in the file listing function, ftp_dflt_list(), to show the write permission for writable files. NOTE: The user will need to override both the write and close default file handlers to provide full support for writing a file.

Chapter 11: FTP Server

355

11.2 File Handlers


Default file handlers are provided. The defaults access the server spec list, which is set up using sspec_addxmemfile(), sauth_adduser() etc. (See Section 8.1.1 on page 219 for more information on the server spec list.) The default file handlers are used when NULL is passed to the initialization function ftp_init().

11.2.1 Replacing the Default Handlers


The FTPhandlers structure contains function pointers to the file handlers. This structure may be passed to ftp_init() to selectively replace the default file handlers. You may provide a NULL pointer for handlers that you do not wish to override. If you have defined FTP_EXTENSIONS then there are an additional two function pointers that should be initialized. typedef struct { int (*open)(); int (*read)(); int (*write)(); int (*close)(); long (*getfilesize)(); int (*dirlist)(); int (*cd)(); int (*pwd)(); #ifdef FTP_EXTENSIONS long (*mdtm)(); int (*delete)(); #endif } FTPhandlers; Starting with Dynamic C 7.30, all FTP server instances share the same set of data handlers. Before this release, there was a separate copy of the handler pointers for each instance of the server. This change does not affect your existing application except to slightly reduce memory usage. This change does add flexibility because it gives any file handler the ability to call any other file handler. In particular, ftp_dflt_list() may now call ftp_dflt_getfilesize() to get the files size

11.2.2 File Handlers Specification


Function descriptions for the default handlers are detailed in this section. Additional information is provided in these descriptions when the default handler does not cover the entire function specification. The default file handlers are in FTPSERVER.LIB.

356

TCP/IP Users Manual

ftp_dflt_open
int ftp_dflt_open( char *name, int options, int uid, int cwd );
DESCRIPTION

Opens a file. If a file is successfully opened, the returned value is passed to subsequent handler routines to identify the particular file or resource, as the 'fd' parameter. If necessary, you can use this number to index an array of any other state information needed to communicate with the other handlers. The number returned should be unique with respect to all other open resource instances, so that your handler does not get confused if multiple FTP data transfers are active simultaneously. Note that the specified file to open may be an absolute or relative path: if the handler supports the concept of directories, then it should handle the path name appropriately and not just assume that the file is in the current directory. If the filename is relative, then the cwd parameter indicates the current directory.
PARAMETERS

name options

The file to open. File access options: O_RDONLY (marks file as read-only). O_WRONLY (not currently supported by the default handler). O_RDWR (not used since its not supported by the FTP protocol).

uid cwd
RETURN VALUE

The userid of the currently logged-in user. Current directory (not currently supported by the default handler).

0: File descriptor of the opened file. FTP_ERR_NOTFOUND: File not found. FTP_ERR_NOTAUTH: Unauthorized user. FTP_ERR_BADMODE: Requested option (2nd parameter) is not supported. FTP_ERR_UNAVAIL: Resource temporarily unavailable.
In the first case, the returned value is passed to subsequent handler routines to identify the particular file or resource, as the 'fd' parameter. If necessary, you can use this number to index an array of any other state information needed to communicate with the other handlers. The number returned should be unique with respect to all other open resource instances, so that your handler does not get confused if multiple FTP data transfers are active simultaneously. Note that the given file name may be an absolute or relative path: if the handler supports the concept of directories, then it should handle the path name as appropriate and not just assume that the file is in the current directory. If the filename is "relative," then the cwd parameter indicates the current directory.

Chapter 11: FTP Server

357

ftp_dflt_getfilesize
long ftp_dflt_getfilesize( int fd );
DESCRIPTION

Return the length of the specified file. This is called immediately after open for a read file. If the file is of a known constant length, the correct length should be returned. If the resource length is not known (perhaps it is generated on-the-fly) then return -1. For write operations, the maximum permissible length should be returned, or -1 if not known.
PARAMETERS

fd
RETURN VALUE

The file descriptor returned when the file was opened.

0: The size of the file in bytes. -1: The length of the file is not known.

358

TCP/IP Users Manual

ftp_dflt_read
int ftp_dflt_read( int fd, char *buf, long offset, int len );
DESCRIPTION

Read file identified by fd. The file contents at the specified offset should be stored into buf, up to a maximum length of len. The return value should be the actual number of bytes transferred, which may be less than len. If the return value is zero, this indicates normal end-of-file. If the return value is negative, then the transfer is aborted. Each successive call to this handler will have an increasing offset. If the getfilesize handler returns a non-negative length, then the read handler will only be called for data up to that length there is no need for such read handlers to check for EOF since the server will assume that only the specified amount of data is available. The return value can also be greater than len. This is interpreted as "I have not put anything in buf. Call me back when you (the server) can accept at least len bytes of data." This is useful for read handlers that find it inconvenient to retrieve data from arbitrary offsets, for example a log reader that can only access whole log records. If the returned value is greater than the server can ever offer, then the server aborts the data transfer. The handler should never ask for more than FTP_MAXLINE bytes.
PARAMETERS

fd buf offset len


RETURN VALUE

The file descriptor returned when the file was opened. Pointer to the buffer to place the file contents. Offset in the file at which copying should begin. The number of bytes to read.

0: EOF. >0: The number of bytes read into buf. -1: Error, transfer aborted.

Chapter 11: FTP Server

359

ftp_dflt_write
int ftp_dflt_write( int fd, char *buf, long offset, int len );
DESCRIPTION

The default write handler does nothing but return zero. The specification states that the handler may write the file identified by fd. buf contains data of length len, which is to be written to the file at the given offset within the file. The return value must be equal to len, or a negative number if an error occurs (such as out of space). The FTP server does not handle partial writes: the given data must be completely written or not at all. If the return code is less than len, an error is assumed to have occurred. Note that it is up to the handler to ensure that another FTP server is not accessing a file which is opened for write. The open call for the other server should return FTP_ERR_UNAVAIL if the current server is writing to a file.
PARAMETERS

fd buf offset len


RETURN VALUE

The file descriptor returned when the file was opened. Pointer to the data to be written. Offset in the file at which to start. The number of bytes to write.

0: The number of bytes written. If this is less than len, an error occurred. -1: Error.

360

TCP/IP Users Manual

ftp_dflt_close
int ftp_dflt_close( int fd );
DESCRIPTION

The default close handler does nothing but return zero. The handler may close the specified file and free up any temporary resources associated with the transfer.
PARAMETERS

fd
RETURN VALUE

The file descriptor returned when the file was opened.

Chapter 11: FTP Server

361

ftp_dflt_list
int ftp_dflt_list( int item, char *line, int listing, int uid, int cwd );
DESCRIPTION

Returns the next file for the FTP server to list. The file name is formatted as a string.
PARAMETERS

item

Index number starting at zero for the first function call. Subsequent calls should be one plus the return value from the previous call. Pointer to location to put the formatted string. Boolean variable to control string form: 0: print file name, permissions, date, etc. 1: print file name only.

line listing

uid cwd
RETURN VALUE

The currently logged-in user. The current working directory.

0: File descriptor for last file listed. -1: Error.

362

TCP/IP Users Manual

ftp_dflt_cd
int ftp_dflt_cd( int cwd, char *dir, int uid );
DESCRIPTION

Change to new "directory." This is called when the client issues a CWD command. The FTP server itself has no concept of what a directory is this is meaningful only to the handler.
PARAMETERS

cwd dir

Integer representing the current directory. String that indicates the new directory that will become the current directory. The interpretation of this string is entirely up to the handler. The dir string will be passed as ".." to move up one level. The currently logged-in user.

uid
RETURN VALUE

0: No such directory exists. -1: Root directory. >0: Anything that is meaningful to the handler.

Chapter 11: FTP Server

363

ftp_dflt_pwd
int ftp_dflt_pwd( int cwd, char *buf );
DESCRIPTION

Print the current directory, passed as cwd, as a string. The result is placed in buf, whose length may be assumed to be at least (FTP_MAXLINE-6). The return value is ignored.
PARAMETERS

cwd buf
RETURN VALUE

The current directory. Pointer to buffer to put the string.

The return value is ignored.

364

TCP/IP Users Manual

ftp_dflt_mdtm
unsigned long ftp_dflt_mdtm( int fd );
DESCRIPTION

This handler function is called when the server receives the FTP command MDTM. The return value of this handler function is the number of seconds that have passed since January 1, 1980. A return value of zero will cause the reply code 213 followed by a space and then the value 19800101000000 (yyyymmddhhmmss) to be sent by the server. The FTP server assumes that this return value is in UTC (Coordinated Universal Time). If SEC_TIMER is running in local time, the handler should make the necessary time zone adjustment so that the return value is expressed in UTC. The handler is only recognized if FTP_EXTENSIONS is defined.
PARAMETERS

fd
RETURN VALUE

File descriptor for the currently opened file.

The number of seconds that have passed since January 1, 1980. The default handler always returns zero. The number of seconds will be converted to a date and time value of the form yyyymmddhhmmss.

Chapter 11: FTP Server

365

ftp_dflt_delete
int ftp_dflt_delete( char *name, int uid, int cwd );
DESCRIPTION

The default handler does not support the delete command. It simply returns the error code for an unauthorized user. The delete handler is only recognized by the server if FTP_EXTENSIONS is defined. It is called when the DELE command is received. The given file name (possibly relative to cwd) should be deleted.
PARAMETERS

name uid cwd


RETURN VALUE

Pointer to the name of a file. The currently logged-in user. The current directory.

0: File was successfully deleted . FTP_ERR_NOTFOUND: File not found. FTP_ERR_NOTAUTH: Unauthorized user. FTP_ERR_BADMODE: Requested option (2nd parameter) is not supported. FTP_ERR_UNAVAIL: Resource temporarily unavailable.

366

TCP/IP Users Manual

11.3 API Functions


The API functions described here, initialize and run the FTP server.

ftp_dflt_is_auth
int ftp_dflt_is_auth( int spec, int options, int uid );
DESCRIPTION

Determine amount of access to a file. If the FTP anonymous user has been set, then also checks that. "options" is how to access the file. Currently, this value is ignored. If the anonymous user ID has been set, then files it owns are globally accessible. Returns whether the user can access it ("owner permission") or if access is because there is an anonymous user ("world permission"). NOTE: This routine only determines accessibility of a name, not whether the user can read and/or write the contents.
PARAMETERS

spec options

Handle to SSPEC file (item). How to access O_RDONLY, O_WRONLY or O_RDWR. Currently this value is ignored. The userID to access as.

uid
RETURN VALUE

0: No access. 1: uid only access. 2: anonymous access (user "anonymous" has been set).
SEE ALSO

sspec_checkaccess

Chapter 11: FTP Server

367

ftp_init
void ftp_init( FTPhandlers *handlers );
DESCRIPTION

Initializes the FTP server. You can optionally specify a set of handlers for controlling what the server presents to the client. This is done with function pointers in the FTPhandlers structure. All FTP server instances share the same list of handlers. The FTPhandlers structure is defined as: typedef struct { int (*open)(char *name, int options, int uid, int cwd); int (*read)(int fd, char *buf, long offset, int len); int (*write)(int fd, char *buf, long offset, int len); int (*close)(int fd); long (*getfilesize)(int fd); int (*dirlist)(int item, char *line, int listing, int uid, int cwd); int (*cd)(int cwd, char *dir, int uid); int (*pwd)(int cwd, char *buf); [long (*mdtm)(int fd);] [int (*delete)(char *name, int uid, int cwd);] } FTPhandlers; If you always provide all your own handlers, then you can define FTP_NODEFAULTHANDLER to eliminate the code for the default handlers. The handlers must be written to the specification described in Section 11.2.2. To use a default handler, leave the field NULL. If you pass a NULL handlers pointer, then the all default handlers will be used. The defaults access the server spec list which is set up using the zserver functions sspec_addxmemfile(), sauth_adduser() etc.
PARAMETERS

handlers

NULL means use default internal file handlers. Otherwise, you must supply a struct of pointers to the various file handlers (open, read, write, close, getfilesize, list). To not override a particular handler, leave it NULL in the structure.

LIBRARY

FTP_SERVER.LIB
SEE ALSO

ftp_tick

368

TCP/IP Users Manual

ftp_load_filenames
int ftp_load_filenames(void)
DESCRIPTION

This function is used in conjunction with the FTP_USE_FS2_HANDLERS macro. It loads the data structure (i.e., the server spec list) that keeps track of the association of filenames to file locations in the file system. The information is loaded from the User block, from the offset given in FTP_USERBLOCK_OFFSET. The function removes any entries from the server spec list that are not FS2 files.
RETURN VALUE

0: Success -1: Failure (possibly due to the filenames having not yet been saved)
SEE ALSO

ftp_save_filenames

Chapter 11: FTP Server

369

ftp_save_filenames
int ftp_save_filenames(void);
DESCRIPTION

This function is used in conjunction with the FTP_USE_FS2_HANDLERS macro. This function saves the data structure (i.e., the server spec list) that keeps track of the association of filenames to file locations in the file system. The information is saved to the User block, at the offset given in FTP_USERBLOCK_OFFSET.
RETURN VALUE

0: Success. -1: Failure, the information could not be saved (due to a write error).
SEE ALSO

ftp_load_filenames

370

TCP/IP Users Manual

ftp_set_anonymous
int ftp_set_anonymous( int uid );
DESCRIPTION

Set the "anonymous" user ID. Resources belonging to this userID may be accessed by any user. A typical use of this function would be ftp_set_anonymous (sauth_adduser("anonymous", "", SERVER_FTP)); which defines an "anonymous" login for the FTP server. This only applies to the FTP server. The username "anonymous" is recommended, since most FTP clients use this for hosts that have no account for the user.
PARAMETER

uid

The user ID to use as the anonymous user. This should have been defined using sauth_adduser(). Pass -1 to set no anonymous user.

RETURN VALUE

Same as the uid parameter, except -1 if uid is invalid.


LIBRARY

FTP_SERVER.LIB
SEE ALSO

sauth_adduser

Chapter 11: FTP Server

371

ftp_shutdown
void ftp_shutdown( int bGraceful );
DESCRIPTION

Close and cancel all FTP connections. If the server is connected to a client, forces the QUIT state. If the application has called tcp_reserveport(), then it must call tcp_clearreserve(). For a graceful shutdown, the application must call tcp_tick() a few more times. After the FTP sockets close, the application must call ftp_init() to again start the server running.
PARAMETER

bGraceful

(boolean) zero to immediately abort all open connections, or nonzero to simulate the QUIT command.

RETURN VALUE

None
LIBRARY

FTP_SERVER.LIB
SEE ALSO

ftp_init

372

TCP/IP Users Manual

ftp_tick
void ftp_tick( void );
DESCRIPTION

Once ftp_init() has been called, ftp_tick() must be called periodically to run the server. This function is non-blocking.
LIBRARY

FTP_SERVER.LIB
SEE ALSO

ftp_init

Chapter 11: FTP Server

373

11.4 Sample FTP Server


This code demonstrates a simple FTP server, using the ftp library. The user "anonymous" may download the file "rabbitA.gif," but not "rabbitF.gif." The user "foo" (with password "bar") may download "rabbitF.gif," but also "rabbitA.gif," since files owned by the anonymous user are world-readable.

Program Name: Samples\tcpip\ftp_server.c


//#define MY_IP_ADDRESS "10.10.6.105" //#define MY_NETMASK "255.255.255.0" //#define MY_GATEWAY "10.10.6.19" #define TCPCONFIG 101 #memmap xmem #use "dcrtcp.lib" #use "ftp_server.lib" #ximport "samples/tcpip/http/pages/rabbit1.gif" rabbit1_gif main(){ int file, user; /* Set up the first file and user */ file = sspec_addxmemfile("rabbitA.gif", rabbit1_gif, SERVER_FTP); user = sauth_adduser("anonymous", "", SERVER_FTP); ftp_set_anonymous(user); sspec_setuser(file, user); sspec_setuser(sspec_addxmemfile("test1", rabbit1_gif, SERVER_FTP), user); sspec_setuser(sspec_addxmemfile("test2", rabbit1_gif, SERVER_FTP), user); /* Set up the second file and user */ file = sspec_addxmemfile("rabbitF.gif", rabbit1_gif, SERVER_FTP); user = sauth_adduser("foo", "bar", SERVER_FTP); sspec_setuser(file, user); sspec_setuser(sspec_addxmemfile("test3", rabbit1_gif, SERVER_FTP), user); sspec_setuser(sspec_addxmemfile("test4", rabbit1_gif, SERVER_FTP), user); sock_init(); ftp_init(NULL); tcp_reserveport(FTP_CMDPORT); while(1) { ftp_tick(); } } // use default handlers // Port 21 // All fields in this section must be // changed to match local // network settings.

374

TCP/IP Users Manual

Each user may execute the "dir" or "ls" command to see a listing of the available files. The listing shows only the files that the logged-in user can access. Notice the definition for TCP_CONFIG. When the value for this macro exceeds 100, a special configuration file is pulled in that will not be overridden by future updates of Dynamic C. In the file CUSTOM_CONFIG.LIB, you may specify any network configuration that suits your purposes. Please see TCP_CONFIG.LIB for examples of setting up a library of configuration options.

11.5 Getting Through a Firewall


If a client is behind a firewall, it is incumbent upon the client to request that the server do a passive open on its data port instead of the normal active open. This is so that the client can then do an active open using the passively opened data port of the server, thus getting through the firewall. Typically the server would not be behind a firewall.

11.6 FTP Server Commands


The following commands are recognized by the FTP server. The reply codes sent in response to these commands are detailed in Section 11.7 on page 377. They are noted here to associate them with the commands that may cause them to be sent.
Table 5. Recognized FTP Server Commands Command Description Possible Reply Codes

ABOR
CDUP CWD

The current data transfer completes before the abort command is read by the server.

226

A special case of CWD (Change Working Directory); the parent of 250, 431 the working directory is changed to be the working directory. Changes working directory. Delete the specified file. 250, 431 250, 450, 550

DELE
LIST

Displays list of files requested by its argument in ls -l format. This 150, 226, 425 gives extra information about the file. Shows the last modification time of the specified file. Confirms the mode of data transmission. Only stream mode is supported. Displays list of files requested by its argument, with names only. This allows an application to further process the files. 213, 250, 450, 550 200, 504 150, 226, 425

MDTM MODE
NLST NOOP

Specifies no action except that the server send an OK reply. It does 200 not affect any parameters or previously entered commands.

Chapter 11: FTP Server

375

Table 5. Recognized FTP Server Commands Command Description Possible Reply Codes

PASS

Password for the user name (sent in clear text). It is accepted only 230, 530 after USER returns code 331 Requests a passive open on a port that is not the default data port. The server responds with the host and port address on which it is 227, 452 listening. Changes the data port from the default port to the port specified in the commands argument. The argument is the concatenation of a 200 32-bit internet host address and a 16-bit TCP port address. Prints the working directory name. 257

PASV

PORT PWD
QUIT RETR

Closes the control connection. If a data transfer is in progress, the 221 connection will not be closed until it has completed. Transfers a copy of the file specified in the pathname argument from the server to the client. Returns the size of the specified file. 150, 226, 425, 550 213, 250, 450, 550

SIZE

STOR

Stores a file from the client onto the server. The file will be 150, 226, 250 overwritten if it already exists at the specified pathname, or it will 425, 450, be created if it does not exist. 452, 550 Confirms the supported structure of a file. Only file-structure is supported: a continuous stream of data bytes. Sends the string RABBIT2000. 200, 504 215

STRU SYST TYPE USER

Confirms the transfer type. The types IMAGE (binary), ASCII and 200, 504 Local with 8-bit bytes are all supported and are treated the same. User name to use for authentication. 331, 530

376

TCP/IP Users Manual

11.7 Reply Codes to FTP Commands


The FTP server replies to all of the commands that it receives. The reply consists of a 3-digit number followed by a space and then a text string explaining the reply. All reply codes sent from the FTP server are listed here.
Reply Code Reply Text

150 200 202 211 213 214 215 220 221 226 227 230 250 257 331 425 450 452 502 504 530 550

File status okay; about to open data connection. Command okay. Command not implemented, superfluous at this site. System status, or system help reply. File status Help message. On how to use the server or the meaning of a particular non-standard command. This reply is useful only to the human user. System type. Service ready for new user. Service closing connection. Closing data connection. Requested file action successful (for example, file transfer or file abort). Entering Passive Mode (h1,h2,h3,h4,p1,p2). User logged in, proceed Requested file action okay, completed.

"PATHNAME" created.
User name okay, need password. Can't open data connection. Requested file action not taken. File unavailable (e.g., file busy). Requested action not taken. Insufficient storage space in system. Command not implemented. Command not implemented for that parameter. Not logged in. Requested action not taken. File unavailable (e.g., file not found, no access).

The text used for the reply codes, may be slightly different than what is shown here. It will be context specific.

Chapter 11: FTP Server

377

378

TCP/IP Users Manual

12. TFTP Client


TFTP.LIB implements the Trivial File Transfer Protocol (TFTP). This standard protocol (internet RFC783) is a lightweight protocol typically used to transfer bootstrap or configuration files from a server to a client host, such as a diskless workstation. TFTP allows data to be sent in either direction between client and server, using UDP as the underlying transport. This library fully implements TFTP, but as a client only. Compared with more capable protocols such as FTP, TFTP:

has no security or authentication is not as fast because of the step-by-step protocol uses fewer machine resources.
Because of the lack of authentication, most TFTP servers restrict the set of accessible files to a small number of configuration files in a single directory. For uploading files, servers are usually configured to accept only certain file names that are writable by any user. If these restrictions are acceptable, TFTP has the advantage of requiring very little 'footprint' in the client host.

12.1 BOOTP/DHCP
In conjunction with DHCP/BOOTP and appropriate server configuration, TFTP is often used to download a kernel image to a diskless host. The target TCP/IP board does not currently support loading the BIOS in this way, since the BIOS and application program are written to non-volatile flash memory. However, the downloaded file does not have to be a binary executable - it can be any reasonably small file, such as an application configuration file. TFTP and DHCP/BOOTP can thus be used to administer the configuration of multiple targets from a central server. Using TFTP with BOOTP/DHCP requires minimal additional effort for the programmer. Just #define the symbol DHCP_USE_TFTP to an integer representing the maximum allowable boot file size (1-65535). See the description of the variables _bootpsize, _bootpdata and _bootperror on page 21 for further details.

Chapter 12: TFTP Client

379

12.2 Data Structure for TFTP


This data structure is used to send and receive. The tftp_state structure, which is required for many of the API functions in TFTP.LIB, may be allocated either in root data memory or in extended memory. This structure is approximately 155 bytes long.

typedef struct tftp_state { byte state; // // // long buf_addr; // word buf_len; // word buf_used; // word next_blk; // word my_tid; // udp_Socket *sock; // longword rem_ip; // longword timeout; // char retry; // char flags; //

Current state. LSB indicates read (0) or write(1). Other bits determine state within this (see below). Physical address of buffer Length of buffer Amount Tx or Rx from/to buffer Next expected block #, or next to Tx UDP port number used by this host UDP socket to use IP address of remote host ms timer value for next timeout retransmit retry counter miscellaneous flags (see below).

// Following fields not used after initial request has been acknowledged. char mode; // Translation mode (see below). char file[129]; // File name on remote host (TFTP server) // - NULL terminated. This field will be // overwritten with a NULL-term error message // from the server if an error occurs. }; The following macros are valid for tftp_state->mode. #define TFTP_MODE_NETASCII 0 #define TFTP_MODE_OCTET 1 #define TFTP_MODE_MAIL 2 // // // // ASCII text 8-bit binary Mail (remote file name is email address, e.g., user@host.blob.org)

12.3 API Functions


Any of the following functions will require approximately 600-800 bytes of free stack. The data buffer for the file to put or to get is always allocated in xram (see xalloc()).

TFTP Session
A session can be either a single download (get) or upload (put). The functions ending with 'x' are versions that use a data structure allocated in extended memory, for applications that are constrained in their use of root data memory.

380

TCP/IP Users Manual

tftp_init
int tftp_init( struct tftp_state *ts );
DESCRIPTION

This function prepares for a TFTP session and is called to complete initialization of the TFTP state structure. Before calling this function, some fields in the structure tftp_state must be set up as follows:
ts->state ts->buf_addr ts->buf_len ts->my_tid ts->sock <0 for read, 1 for write> <physical address of xmem buffer> <length of physical buffer, 0-65535> <UDP port number. Set 0 for default> <address of UDP socket (udp_Socket *),or NULL to use DHCP/BOOTP socket> ts->rem_ip = <IP address of TFTP server host, or zero to use default BOOTP host> ts->mode = <one of the following constants: TFTP_MODE_NETASCII (ASCII text) TFTP_MODE_OCTET (8-bit binary) TFTP_MODE_MAIL (Mail)> strcpy(ts->file, <remote filename or mail address>) = = = = =

Note that mail mode can only be used to write mail to the TFTP server, and the file name is the e-mail address of the recipient. The e-mail message must be ASCII-encoded and formatted with RFC822 headers. Sending e-mail via TFTP is deprecated. Use SMTP instead since TFTP servers may not implement mail.
PARAMETERS

ts
RETURN VALUE

Pointer to tftp_state.

0: OK. -4: Error, default socket in use.


LIBRARY

TFTP.LIB

Chapter 12: TFTP Client

381

tftp_initx
int tftp_initx( long ts_addr );
DESCRIPTION

This function is called to complete initialization of the TFTP state structure, where the structure is possibly stored somewhere other than in the root data space. This is a wrapper function for tftp_init(). See that function description for details.
PARAMETERS

ts_addr
RETURN VALUE

Physical address of TFTP state (struct tftp_state)

0: OK -1: Error, default socket in use


LIBRARY

TFTP.LIB

382

TCP/IP Users Manual

tftp_tick
int tftp_tick( struct tftp_state *ts );
DESCRIPTION

This function is called periodically in order to take the next step in a TFTP process. Appropriate use of this function allows single or multiple transfers to occur without blocking. For multiple concurrent transfers, there must be a unique tftp_state structure, and a unique UDP socket, for each transfer in progress. This function calls sock_tick().
PARAMETERS

ts

Pointer to TFTP state. This must have been set up using tftp_init(), and must be passed to each call of tftp_tick() without alteration.

RETURN VALUE

1: OK, transfer not yet complete. 0: OK, transfer complete -1: Error from remote side, transfer terminated. In this case, the ts_addr->file field will be overwritten with a NULL-terminated error message from the server. -2: Error, could not contact remote host or lost contact. -3: Timed out, transfer terminated. -4: (not used) -5: Transfer complete, but truncated -- buffer too small to receive the complete file.
LIBRARY

TFTP.LIB

Chapter 12: TFTP Client

383

tftp_tickx
int tftp_tickx( long ts_addr );
DESCRIPTION

This function is a wrapper for calling tftp_tick(), where the structure is possibly stored somewhere other than in the root data space. See that function description for details.
PARAMETERS

ts_addr
RETURN VALUE

Physical address of TFTP state (struct tftp_state).

1: OK, transfer not yet complete. 0: OK, transfer complete -1: Error from remote side, transfer terminated. In this case, the ts_addr->file field will be overwritten with a NULL-terminated error message from the server. -2: Error, could not contact remote host or lost contact. -3: Timed out, transfer terminated. -4: (not used) -5: Transfer complete, but truncated -- buffer too small to receive the complete file.
LIBRARY

TFTP.LIB

384

TCP/IP Users Manual

tftp_exec
int tftp_exec( char put, long buf_addr, word *len, int mode, char *host, char *hostfile, udp_Socket *sock );
DESCRIPTION

Prepare and execute a complete TFTP session, blocking until complete.This function is a wrapper for tftp_init() and tftp_tick(). It does not return until the complete file is transferred or an error occurs. Note that approximately 750 bytes of free stack will be required by this function.
PARAMETERS

put buf_addr len

0: get file from remote host; 1: put file to host. Physical address of data buffer. Length of data buffer. This is both an input and a return parameter. It should be initialized to the buffer length. On return, it will be set to the actual length received (for a get), or unchanged (for a put). Data representation: 0=NETASCII, 1=OCTET (binary), 2=MAIL. Remote host name, or NULL to use default BOOTP host. Name of file on remote host, or e-mail address for mail. UDP socket to use, or NULL to re-use BOOTP socket if available.

mode host hostfile sock


RETURN VALUE

0: OK, transfer complete. -1: Error from remote side, transfer terminated. In this case, ts_addr->file will be overwritten with a NULL-terminated error message from the server. -2: Error, could not contact remote host or lost contact. -3: Timed out, transfer terminated -4: sock parameter was NULL, but BOOTP socket was unavailable.
LIBRARY

TFTP.LIB

Chapter 12: TFTP Client

385

386

TCP/IP Users Manual

13. SMTP Mail Client


SMTP (Simple Mail Transfer Protocol) is one of the most common ways of sending e-mail. SMTP is a simple text conversation across a TCP/IP connection. The SMTP server usually resides on TCP port 25 waiting for clients to connect. Sending mail with the SMTP.LIB client library is a four-step process. First, build your e-mail message, then call smtp_sendmail(). Next, repetitively call smtp_mailtick() while it is returning SMTP_PENDING. Finally, call smtp_status() to determine if the mail was sent successfully. There is a sample program in Section 13.4 that outlines how to send a simple mail message.

13.1 Sample Conversation


The following is a typical listing of mail from the controller (me@somewhere.com) to someone@somewhereelse.com. The mail server that the controller is talking to is mail.somehost.com. The lines that begin with a numeric value are coming from the mail server. The other lines were sent by the controller. More information on the exact specification of SMTP and the meanings of the commands and responses can be found in RFC821 at http://www.ietf.org.

220 mail.somehost.com ESMTP Service (WorldMail 1.3.122) ready HELO 10.10.6.100 250 mail.somewhere.com MAIL FROM: <me@somewhere.com> 250 MAIL FROM:<me@somewhere.com> OK RCPT TO: <someone@somewhereelse.com> 250 RCPT TO:<someone@somewhereelse.com> OK DATA 354 Start mail input; end with <CRLF>.<CRLF> From: <me@somewhere.com> To: <someone@somewhereelse.com> Subject: test mail test mail . 250 Mail accepted QUIT 221 mail.somehost.com QUIT You can see a listing of the conversation between your controller and the mail server by defining the SMTP_DEBUG macro at the top of your program. Note that there must be a blank line after the line Subject: test mail.

Chapter 13: SMTP Mail Client

387

13.2 Configuration Macros


The SMTP client is configured by using compiler macros.

SMTP_DEBUG
This macro tells the SMTP code to log events to the STDIO window in Dynamic C. This provides a convenient way of troubleshooting an e-mail problem.

SMTP_DOMAIN
This macro defines the text to be sent with the HELO client command. Many mail servers ignore the information supplied with the HELO, but some e-mail servers require the fully qualified name in this field (i.e., somemachine.somedomain.com). If you have problems with e-mail being rejected by the server, turn on SMTP_DEBUG. If it is giving an error message after the HELO line, talk to the administer of the machine for the appropriate value to place in SMTP_DOMAIN. If you do not define this macro, it will default to MY_IP_ADDRESS. #define SMTP_DOMAIN "somemachine.somedomain.com"

SMTP_SERVER
This macro defines the mail server that will relay the controllers mail. This server must be configured to relay mail for your controller. You can either place a fully qualified domain name or an IP address in this field. #define SMTP_SERVER "mail.mydomain.com" or #define SMTP_SERVER "10.10.6.19"

SMTP_TIMEOUT
This macro tells the SMTP code how long in seconds to try to send the e-mail before timing out. It defaults to 20 seconds. #define SMTP_TIMEOUT 10

388

TCP/IP Users Manual

13.3 API Functions smtp_sendmail


void smtp_sendmail(char *to, char *from, char *subject, char *message);
DESCRIPTION

This function initializes the internal data structures with strings for the to e-mail address, the from e-mail address, the subject, and the body of the message. You should not modify these strings until smtp_mailtick() no longer returns SMTP_PENDING.
PARAMETERS

to from subject message

String containing the e-mail address of the destination. String containing the e-mail address of the source. String containing the subject of the message. String containing the message. (This string must not contain the byte sequence "\r\n.\r\n" (CRLF.CRLF), as this is used to mark the end of the e-mail, and will be appended to the e-mail automatically.)

RETURN VALUE

None.
LIBRARY

SMTP.LIB

Chapter 13: SMTP Mail Client

389

smtp_sendmailxmem
void smtp_sendmailxmem(char *to, char *from, char *subject, long message, long messagelen);
DESCRIPTION

This function initializes the internal data structures with strings for the to e-mail address, the from e-mail address, the subject, and the body of the message. You should not modify these strings until smtp_mailtick() no longer returns SMTP_PENDING.
PARAMETERS

to from subject message

String containing the e-mail address of the destination. String containing the e-mail address of the source. String containing the subject of the message. Physical address in xmem containing the message. (The message must NOT contain the byte sequence "\r\n.\r\n" (CRLF.CRLF), as this is used to mark the end of the e-mail, and will be appended to the e-mail automatically.) Length of the message in xmem.

messagelen
RETURN VALUE

None
LIBRARY

SMTP.LIB

390

TCP/IP Users Manual

smtp_mailtick
int smtp_mailtick(void);
DESCRIPTION

Repetitively call this function until e-mail is completely sent. For a small message, this function will need to be called about 20 times to send the message. The number of times will vary depending on the latency of you connection to the mail server and the size of your message.
RETURN VALUE

SMTP_SUCCESS - e-mail sent. SMTP_PENDING - e-mail not sent yet call smtp_mailtick again. SMTP_TIME - e-mail not sent within SMTP_TIMEOUT seconds. SMTP_UNEXPECTED - received an invalid response from SMTP server.
LIBRARY

SMTP.LIB

Chapter 13: SMTP Mail Client

391

smtp_status
int smtp_status(void);
DESCRIPTION

Return the status of the last e-mail processed.


RETURN VALUE

SMTP_SUCCESS - e-mail sent. SMTP_PENDING - e-mail not sent yet call smtp_mailtick again. SMTP_TIME - e-mail not sent within SMTP_TIMEOUT seconds. SMTP_UNEXPECTED - received an invalid response from SMTP server.
LIBRARY

SMTP.LIB

392

TCP/IP Users Manual

13.4 Sample Sending of an E-mail


This program, smtp.c, uses the SMTP library to send an e-mail. For an example of using smtp_sendmailxmem(), see the sample program samples\tcpip\smtp\smtpxmem.c.

Program Name: Samples\tcpip\smtp\smtp.c


/* Pick the predefined TCP/IP configuration for this sample. * It is best to explicitly turn off DHCP in your configuration. This will allow the * console to completely manage DHCP, so that it does not acquire the lease at startup * in sock_init() when it may not need to (if the user has not turned on DHCP). */ #define TCPCONFIG 1 /* Change these macros to the appropriate values or change the * smtp_sendmail(...) call in main() to reference your values. */ #define #define #define #define FROM TO SUBJECT BODY "myaddress@mydomain.com" "myaddress@mydomain.com" "test mail" "You've got mail!"

/* SMTP_SERVER tells DCRTCP where your mail server is. This value can be * the name or the IP address. */ #define SMTP_SERVER "mymailserver.mydomain.com" #memmap xmem #use dcrtcp.lib #use smtp.lib main() { sock_init(); smtp_sendmail(FROM, TO, SUBJECT, BODY); while(smtp_mailtick()==SMTP_PENDING) continue; if(smtp_status()==SMTP_SUCCESS) printf("Message sent\n"); else printf("Error sending message\n"); }

Chapter 13: SMTP Mail Client

393

394

TCP/IP Users Manual

14. POP3 Client


Post Office Protocol version 3 (POP3) is probably the most common way of retrieving e-mail from a remote server. Most e-mail programs, such as Eudora, MS-Outlook, and Netscapes e-mail client, use POP3. The protocol is a fairly simple text-based chat across a TCP socket, normally using TCP port 110. There are two ways of using POP3.LIB. The first method provides a raw dump of the incoming e-mail. This includes all of the header information that is sent with the e-mail, which, while sometimes useful, may be more information than is needed. The second method provides a parsed version of the e-mail, with the sender, recipient, subject line, and body text separated out. In both methods, each line of e-mail has CRLF stripped from it and \0 appended to it.

14.1 Configuration
The POP3 client can be configured through the following macros:

POP_BUFFER_SIZE
This will set the buffer size for POP_PARSE_EXTRA in bytes. These are the buffers that hold the sender, recipient and subject of the e-mail. POP_BUFFER_SIZE defaults to 64 bytes.

POP_DEBUG
This will turn on debug information. It will show the actual conversation between the device and the remote mail server, as well as other useful information.

POP_NODELETE
This will stop the POP3 library from removing messages from the remote server as they are read. By default, the messages are deleted to save storage space on the remote mail server.

POP_PARSE_EXTRA
This will enable the second mode, creating a parsed version of the e-mail as mentioned above. The POP3 library parses the incoming mail more fully to provide the Sender, Recipient, Subject, and Body fields as separate items to the call-back function.

Chapter 14: POP3 Client

395

14.2 Steps to Receive E-mail.


1. pop3_init()is called to provide the POP3 library with a call-back function. This callback will be used to provide you the incoming data. This function is usually called once. 2. pop3_getmail() is called to start the e-mail being received, and to provide the library with e-mail account information. 3. pop3_tick() is called as long as it returns POP_PENDING, to actually run the library. The library will call the function you provided pop3_init() several times to give you the e-mail.

14.3 Call-Back Function


There are two types of call-back functions, which are described here.

14.3.1 Normal call-back


When not using POP_PARSE_EXTRA, you need to provide a function with the following prototype: int storemail(int number, char *buf, int size); The parameter number is the number of the e-mail being transferred, usually 1 for the first, 2 for the second, but not necessarily. The numbers are only guaranteed to be unique between all e-mails transferred. The buf parameter is the text buffer containing one line of the incoming e-mail. This must be copied out immediately, as the buffer will be different when the next line comes in, and your callback is called again. size is the number of bytes in buf. The sample program Samples\tcpip\pop3\ pop.c provides an example of this style of call-back.

14.3.2 POP_PARSE_EXTRA call-back


If POP_PARSE_EXTRA is defined, you need to provide a call-back function with the following prototype: int storemail(int number, char *to, char *from, char *subject, char *body, int size); number, body, and size are the same as before. to has the e-mail address of who this e-mail was sent to. from has the e-mail address of who sent this e-mail. subject has the subject line of the e-mail. These new fields should be used only the first time your call-back is called with a new number field. In subsequent calls, these fields are not guaranteed to have accurate information. See parse_extra.c in Section 14.5 for an example of this type of call-back.

396

TCP/IP Users Manual

14.4 API Functions pop3_init


int pop3_init(int (*storemail)());
DESCRIPTION

This function must be called before any other POP3 function is called. It will set the callback function where the incoming e-mail will be passed to. This probably should only be called once.
PARAMETERS

storemail
RETURN VALUE

A function pointer to the call-back function.

0: Success. 1: Failure.
LIBRARY

POP3.LIB

Chapter 14: POP3 Client

397

pop3_getmail
int pop3_getmail(char *username, char *password, long server);
DESCRIPTION

This function will initiate receiving e-mail (a POP3 request to a remote e-mail server). IMPORTANT NOTE - the buffers for username and password must NOT change until pop3_tick() returns something besides POP_PENDING. These values are not saved internally, and depend on the buffers not changing.
PARAMETERS

username password server

The username of the account to access. The password of the account to access. The IP address of the server to connect to, as returned from resolve().

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

POP3.LIB

398

TCP/IP Users Manual

pop3_tick
int pop3_tick(void)
DESCRIPTION

A standard tick function, to run the daemon. Continue to call it as long as it returns POP_PENDING.
RETURN VALUE

POP_PENDING: Transfer is not done; call pop3_tick again. POP_SUCCESS: All e-mails were received successfully. POP_ERROR: Unknown error occurred. POP_TIME: Session timed-out. Try again, or use POP_TIMEOUT to increase the timeout length.
LIBRARY

POP3.LIB

Chapter 14: POP3 Client

399

14.5 Sample Receiving of E-mail


This program connects to a POP3 server and downloads e-mail from it.

Program Name: Samples\tcpip\pop3\parse_extra.c


#define TCPCONFIG 1 #define POP_HOST mail.domain.com" #define POP_USER "myname" #define POP_PASS "secret" #define POP_PARSE_EXTRA #memmap xmem #use "dcrtcp.lib" #use "pop3.lib" int n; // Name of your POP3 server // Username for POP3 account // Password for POP3 account

int storemsg(int num, char *to, char *from, char *subject, char *body, int len){ #GLOBAL_INIT{n = -1;} if(n != num) { n = num; printf("RECEIVING MESSAGE <%d>\n", n); printf("\tFrom: %s\n", from); printf("\tTo: %s\n", to); printf("\tSubject: %s\n", subject); } printf("MSG_DATA> '%s'\n", body); return 0; } main(){ static long address; static int ret; sock_init(); pop3_init(storemsg); printf("Resolving name...\n"); address = resolve(POP_HOST); printf("Calling pop3_getmail()...\n"); pop3_getmail(POP_USER, POP_PASS, address); printf("Entering pop3_tick()...\n"); while((ret = pop3_tick()) == POP_PENDING) continue; if(ret == POP_SUCCESS) printf("POP was successful!\n"); if(ret == POP_TIME) printf("POP timed out!\n"); if(ret == POP_ERROR) printf("POP returned a general error!\n"); printf("All done!\n"); } // Request to server //set up call-back

400

TCP/IP Users Manual

14.5.1 Sample Conversation


The following is an example POP3 session from the specification in RFC1939. For more information see: http://www.rfc-editor.org/rfc/std/std53.txt In the following example, lines starting with S: are from the server, and lines starting with C: are from the client. S: C: S: C: S: C: S: C: S: S: S: S: C: S: S: S: C: S: C: S: S: S: C: S: C: S: C: S: <wait for connection on TCP port 110> <open connection> +OK POP3 server ready <1896.697170952@dbc.mtview.ca.us> APOP mrose c4c9334bac560ecc979e58001b3e22fb +OK mrose's maildrop has 2 messages (320 octets) STAT +OK 2 320 LIST +OK 2 messages (320 octets) 1 120 2 200 . RETR 1 +OK 120 octets <the POP3 server sends message 1> . DELE 1 +OK message 1 deleted RETR 2 +OK 200 octets <the POP3 server sends message 2> . DELE 2 +OK message 2 deleted QUIT +OK dewey POP3 server signing off (maildrop empty) <close connection> <wait for next connection>

For debugging purposes, you can observe this conversation by defining POP_DEBUG at the top of your program.

Chapter 14: POP3 Client

401

402

TCP/IP Users Manual

15. SNMP
Simple Network Management Protocol (SNMP) is a popular network management tool. Traditionally, SNMP was designed and used to gather statistics for network management and capacity planning. For example, the number of packets sent and received on each network interface could be obtained. But because of its simplicity, SNMP use has expanded into areas of interest to embedded systems. It is now used for many vendor-specific management functions, e.g., showing a thermostat temperature, machine tool RPM or whether the front door was left open. The SNMP library, SNMP.LIB, implements version 1 of the SNMP protocol. It is available as an add-on module that may be purchased from our website: www.zworld.com. After reading this chapter and studying and running the provided demo program, you will be able to:

define a MIB code and run an SNMP agent


Before we get into the implementation details, lets discuss SNMP from a conceptual level.

15.1 SNMP Overview


The SNMP model is client/server based. The SNMP agent is the server part, passively listening for communication from an SNMP managerthe client side of things. The SNMP manager, a software module running on a Network Management Station (NMS), may make one of three possible requests: Get, GetNext or Set. These requests are made via SNMP messages. SNMP allows managers and agents to exchange SNMP messages for the purpose of sharing information about managed objects. The messages are embedded in UDP datagrams for transmission. Their format is:

version community

PDU(s)

Figure 1. SNMPv1 message format

version: version of SNMP being used, 1, 2 or 3. Version 1 is supported in Dynamic C 7.30. community: used for trivial authentication. PDU: stands for Protocol Data Unit, another name for a packet. These are generated and parsed
internally. A PDU contains the type of message (get, getnext, set, response or trap) and a list of affected objects, called the variable binding. The variable binding is a list of name and value pairs either to get or to set.

Chapter 15: SNMP

403

15.1.1 Managed Objects


A managed object can be a device or a device characteristic: e.g., the value of a temperature gauge, the setting of a switch or any other logical or physical component of an embedded system. Instances of managed objects are kept in a Management Information Base (MIB). Each managed object has a unique name, which is known as its object identifier, or OID. The rules for naming and defining managed objects are specified by Structured Management Information (SMI). This formal definition is compiled by the SNMP manager, allowing the manager to understand the structure of the MIB on the managed device. In Section 15.2 we will look at a demo program that will clearly illustrate the correspondence between the SMI defined MIB used by the SNMP manager and the MIB used by the SNMP agent.

15.1.2 SNMP Agent


An agent listens on UDP port 161 (SNMP_PORT) of its device for SNMP messages from a manager. Programmatically, the SNMP agent is fairly simple. Any complexity lies in the organization of the managed objects that the agent accesses. The agent sends messages back to the manager in response to the get, get-next and set requests that it receives. For a get-next request, the agent returns the next OID in lexicographic order from the OID specified in the variable binding of the PDU. Both get and set requests are atomic. They may request acting on multiple managed objects, but the agent will only process the request if all of the managed objects are accessible. Agents may also send unsolicited messages to a manager. These unsolicited messages are called traps. They may be used to signal the manager that something has gone wrong, (perhaps a variable has gone out of range or a light bulb has burned out) or they may be used for informational purposes.

404

TCP/IP Users Manual

15.1.3 MIBs
A MIB is a structured arrangement of managed objects a database that maps OIDs to actual variable instances. The MIB may be used as a stand-alone hierarchical database without SNMP if desired. Instances of managed objects are always leaf nodes. And only leaf nodes may be accessed using SNMP.

ccitt (0) standard (0) registrationauthority (1)

iso (1) memberbody (2)

iso-ccitt (2) identifiedorganization(3)

dod (6)

internet (1) directory (1) mgmt (2) experimental (3) private (4) security (5) snmpV2 (6)

mib-2 (1)

enterprise (1)
... ...

system (1) if (2)

ip (4)

icmp (5)

tcp (6)

udp (7)

Rabbit Semiconductor (12807)

Z-World Inc. (12817)

Figure 2. MIB tree diagram from root node down to MIB-II and enterprise subtrees

15.1.3.1 MIB-II Subtree MIB-II has nine groups, six of which are usually of interest: system, if, ip, icmp, udp and tcp. Access to lots of useful information has been standardized by MIB-II. For example, in the system group are managed objects named sysContact, sysName and sysLocation. If set, they give the name and phone number of the person responsible for the device, the device name and its physical location. The interfaces group (if) holds information about each interface on a device. The rest of the group names should be familiar. For those interested in the descriptions of managed objects in MIB-II, read chapter 3 in a A Practical Guide to SNMPv3 and Network Management by David Zeltserman. Note that Dynamic C does not currently implement any of the MIB-II objects, since it does not support network router functionality.
Chapter 15: SNMP 405

15.1.3.2 Enterprise Subtree The enterprise subtree is of special interest because it is where you can stake out a personal piece of the brave, new MIB world. In Figure 2, notice that both Rabbit Semiconductor and Z-World have nodes on the enterprise subtree. Enterprise numbers are assigned by the Internet Assigned Numbers Authority (IANA). Our assigned enterprise numbers are:

12807 - Rabbit Semiconductor 12817 - Z-World Inc.


In Section 15.2.5.1 we will examine the Rabbit Semiconductor subtree. To obtain an assigned enterprise number go to: http://www.iana.org/cgi-bin/enterprise.pl

15.1.4 SMI
Structure of Management Information (SMI) gives the rules for naming and defining the managed objects that are stored in a MIB. The actual storage of instances of managed objects is done programmatically by the SNMP agent, with the values being stored on the managed device. The definitions of managed objects required by SMI are compiled by SNMP managers. This is a standard that the manager uses in order to know what managed objects the agent can access and where they are logically located. Object Name (OID) SMI specifies a hierarchical naming scheme. The OID of an object is a series of non-negative integers traversing the tree to the node of the object. Object Definition SMI specifies the allowable data types, information organization and the encoding rules used (BER).

406

TCP/IP Users Manual

Object Data Types Managed objects must be reducible to the data types defined for SNMP. The following table shows the mappings from the SMI defined types to the internal types used by the MIB.LIB implementation to store an object in the MIB tree.
SMI Defined Data Type INTEGER Internal Data Type

SNMP_SHORT SNMP_LONG SNMP_OCT


OCTECT STRING

SNMP_FOCT SNMP_STR

OBJECT IDENTIFIER NULL

SNMP_OID SNMP_NULL SNMP_LONG SNMP_LONG SNMP_LONG SNMP_LONG

IpAddress Counter Gauge TimeTicks

The internal data types are specified in the following table:


Internal Type Representation

SNMP_SHORT SNMP_LONG SNMP_STR

2-byte integer in Rabbit order (little endian) 4-byte integer in Rabbit order Null terminated string, with specified maximum length. The null terminator is not counted in computing the string length. The null is only appended if the string is less than its maximum length. 2-byte unsigned length field, followed by data. The length field contains the actual data length, not including the 2 bytes for the length field itself. Fixed length binary data. The length is always equal to the maximum length specified. Object identifier as defined by the snmp_oid structure.

SNMP_OCT

SNMP_FOCT SNMP_OID

The easiest way to understand this information is to look at the provided demo program as an example.

Chapter 15: SNMP

407

15.2 Demo Program


The sample program SNMP1.C implements an SNMP agent that will run on any Ethernet-enabled Rabbit-based target. The code fragments in this section are from SNMP1.C. To see the program in its entirety, open up the source code file located at Samples\tcpip\snmp. #memmap xmem // This is necessary for all SNMP applications. It causes inclusion of SNMP.LIB and MIB.LIB #define USE_SNMP 1 // This must be defined to support trap sending #define SNMP_TRAPS // Standard DCRTCP network definitions. Change to suit your site requirements. #define TCPCONFIG 1 // Set the IP address of the SNMP manager that will receive trap messages. #define MANAGER_IP "10.10.6.178" // For this demo only, send trap every 5 seconds. #define SEND_TRAPS // Rabbit Semiconductor (do not change) #define SNMP_ENTERPRISE 12807 #use "dcrtcp.lib" The network definitions (TCPCONFIG) pertain to the target on which SNMP1.C is running. MANAGER_IP identifies the SNMP manager to which SNMP traps are sent. The configuration macro SNMP_TRAP_PORT will default to UDP port 162 if it is not defined in the initialization code of the application.

408

TCP/IP Users Manual

15.2.1 Creating Managed Objects


The variable definitions in the following code fragment are the managed objects that the agent will store in a MIB. // Managed variables. Read/write. int rw_int; long rw_long; char rw_fixed[20]; char rw_str[20]; char rw_oct[22]; snmp_oid rw_oid; longword trapdest_ip; longword rw_tt; // Managed variables. Read-only. int r_int; long r_long; char r_fixed[20]; char r_str[20]; char r_oct[22]; snmp_oid r_oid; The data structure snmp_oid is an internal data structure defined in MIB.LIB. It is used to hold the OID of a managed object. Another ubiquitous data structure, snmp_parms, is also defined in MIB.LIB. It is used to pass parameters to most of the API functions described in Section 15.4.

Chapter 15: SNMP

409

15.2.2 Callback Functions


Callback functions provide a way to customize data handling. The callback is invoked by the SNMP agent for each get or set request. If there is no callback for a particular object, then access to that object is always granted (according to the read/write masks). The callback function should be defined as follows: int my_callback (snmp_parms *p, int wr, int commit, void *v, word *len, word maxlen)
PARAMETERS

snmp_parms contains most of the information about the access. It is set up with the full OID of the object, plus its current value. This parameter is non-zero if this is a write access, otherwise it is a read access. This parameter implements a 2-stage query/commit process. It is necessary because any single SNMP request must be performed fully or not at all, i.e., the agent will only process the request if access to all of the managed objects in the variable binding is granted. Read Request: commit is always zero for read requests. The callback is only invoked once, not twice as it is for write requests. Write Request: When commit is equal to zero, the agent is checking the availability of the managed object. The callback should return zero to continue or non-zero to deny access. If at least one callback function denies access, no change will be made to any object in the transaction, and none of the callbacks will be called with commit equal to true. When commit is not equal to zero, the callback function should skip checking the availability of the managed object (that was done the first time around) and just perform the desired side-effects associated with the write access. The callbacks return value will be ignored.

wr

commit

Void pointer to a temporary location that may be altered by the callback. If the managed object is an integer, v points to a longword. If it is an OID, then v points to a structure of type snmp_oid. Otherwise, it points to the first character of a temporary buffer containing the string. Points to the length of the string that is pointed to by v. Note that this is used by the SNMP agent to determine the string length. The maximum allowable length of the buffer pointed to by v.
TCP/IP Users Manual

len

maxlen
410

RETURN VALUE

The non-zero return value may be chosen from SNMP_ERR_* definitions, in which case the value is used as the error type for the response. Otherwise, SNMP_ERR_genErr is used. Read callbacks are used for SNMP get/get-next requests, as well as immediately after SNMP set requests, where the updated value of the variable is read back for generating the response. The return code for read callbacks is currently ignored, but should be set to zero for OK or non-zero for invalid (if applicable), to allow upward compatibility. 15.2.2.1 Callback Function Example A callback function may be used for special actions that must be taken when a variable is written by the SNMP agent, such as creating entire table rows. Another use is to transform between internal and external representations. For example, the callback function shown below demonstrates how to scale a variable from internal units into the units expected by the SNMP manager. In this case, the variable appears as 1/10th of its internal value. Note that the transformation needs to work both ways if the variable is writable by the SNMP manager. int scale(snmp_parms *p, int wr, int commit, long *v, word *len, word maxlen){ printf("Callback: wr=%d commit=%d v(in)=%ld ", wr, commit, *v); if (wr) { // On write by agent, we ensure that the variable is within bounds. if (*v > 200000000) return SNMP_ERR_badValue; if (*v < -200000000) return SNMP_ERR_badValue; // OK, scale it up to internal representation. *v *= 10; } else // Read by the agent. Convert internal to external *v /= 10; printf("v(out)=%ld\n", *v); return 0; } The callback function has the opportunity to manipulate the value (including its length) as well as say whether the write operation is allowed or not.

Chapter 15: SNMP

411

15.2.3 Creating Communities


Before the MIB is created, variables are defined and some initialization takes place. int main() { auto snmp_parms _p; auto snmp_parms *p; auto word tt; auto word trapindices[2]; auto word monindex; // Set the community passwords snmp_set_dflt_communities("public", "private", "trap"); // Set p to be a pointer to _p, for calling convenience. p = &_p; // Set parameter structure to default initial state (required). snmp_init_parms(p); There are 3 communities defined in this SNMP agent. The public and private communities are defined by default and the trap community is defined with the inclusion of #define SNMP_TRAPS at the beginning of the program. The configuration macro SNMP_MAX_COMMUNITIES limits the number of distinct community names. It will be set to 3 in this SNMP agent. It must be at least 1. To add another community, call the API function snmp_add_community(). The return value of this function is used to set the password for the new community, by passing it as a parameter to snmp_set_community(). Each new community requires SNMP_MAX_COMMUNITIES to be increased by 1.

412

TCP/IP Users Manual

15.2.4 Creating the MIB


The MIB is created by the following code: // define the root of this MIB tree p = snmp_append_parse_stem(p, "3.1.1"); // make the following managed objects both readable and writable p = snmp_set_access(p, SNMP_PUBLIC_MASK|SNMP_PRIVATE_MASK, SNMP_PRIVATE_MASK); p = snmp_add_int(p, "1.1.0", &rw_int); monindex = snmp_last_index(p); p = snmp_set_callback(p, scale); p = snmp_add_long(p, "1.2.0", &rw_long); p = snmp_set_callback(p, NULL); p p p p p p = = = = = = // Save index 4 later monitor call // Setup for callback function // Associate callback with var // Dont associate with other vars

snmp_add_foct(p, "1.3.0", rw_fixed, 20); snmp_add_str(p, "1.4.0", rw_str, 20); snmp_add_oct(p, "1.5.0", rw_oct, 22); snmp_add_objectID(p, "1.6.0", &rw_oid); snmp_add_ipaddr(p, "1.7.0", &trapdest_ip); snmp_add_timeticks(p, "1.8.0", &rw_tt);

// make the following managed objects read only p = snmp_set_access(p, SNMP_PUBLIC_MASK|SNMP_PRIVATE_MASK, 0); p = snmp_add_int(p, "2.1.0", &r_int); trapindices[0] = snmp_last_index(p); // save index for trap message p = snmp_add_long(p, "2.2.0", &r_long); p = snmp_add_foct(p, "2.3.0", r_fixed, 20); p = snmp_add_str(p, "2.4.0", r_str, 20); p = snmp_add_oct(p, "2.5.0", r_oct, 22); trapindices[1] = snmp_last_index(p); // save index for trap message p = snmp_add_objectID(p, "2.6.0", &r_oid); All of the API functions that were used to create the MIB are described in Section 15.4. A pointer to the parameter structure, snmp_parms, was passed to all functions, and also set to the return value. This is the recommended way of doing the MIB tree setup, since if any step fails it will return NULL. Passing the NULL on to subsequent functions is harmless, and avoids the need to do error checking after each call. Only at the end of sequence should "p" be tested for NULL.

Chapter 15: SNMP

413

Notice that the root of the MIB tree is set to SNMP_ENTERPRISE.oemExperiments.demos.rabbitsemiDemoSNMP1 using the call: p = snmp_append_parse_stem(p, "3.1.1"); The entire MIB tree can be rooted at a different point simply by changing this one call. But wait, you may well ask, where did the oemExperiments.demos. etc., come from? Before I answer that, lets look at a tree diagram of the MIB that was created in the previous code fragment. The initial OID stem is set to 43.6.1.4.1.SNMP_ENTERPRISE by the call to snmp_init_parms(). The first two levels in the tree, iso.org (1.3) are condensed to 43 to save transmitting an extra byte. The first 1 in 1.3.6.1.4.1 is multiplied by 40 then added to the second number 3, resulting in 1*40+3=43 or 0x2b. This initial OID corresponds to the Rabbit Semiconductor node (rabbitsemi) on the enterprise subtree. Leaf nodes are created using the snmp_add_* macros. After the leaf node for rw_tt is created, access is set to read-only for the remainder of the managed objects. Addition of each object requires the additional levels below the root OID specified in the call to snmp_append_parse_stem(). By convention, objects with a single instance, i.e., not tabular, always have a zero at their lowest level.

enterprise (1)

. . .

Rabbit Semiconductor (12807) (3) (1) (1)

Z-World Inc. (12817)

(1)

(2)

rw_int (1.0) rw_long (2.0) . . .

rw_tt (8.0)

r_int (1.0)

r_long (2.0)

. . .

r_oid (6.0)

414

TCP/IP Users Manual

But we still dont know where the oemExperiments.demos.rabbitsemiDemoSNMP1 part comes in, unless you cheated and already looked in the text files that were named in the instructions at the beginning of SNMP1.C. These files:

RABBITSEMI-SMI.txt - top level Rabbit Semiconductor RABBITSEMI-PRODUCTS-MIB.txt - listing of products (boards) RABBITSEMI-DEMO-SNMP1.txt - describes this demo.
contain the SMI definitions that are used by the SNMP manager.

15.2.5 Defining Managed Objects with SMI


The SNMP manager must compile the relevant .txt files that define a MIB that is compatible with the structure of the MIB defined by the SNMP agent. 15.2.5.1 Defining the Rabbit Subtree The text file RABBITSEMI-SMI.txt defines the top level of the Rabbit Semiconductor subtree. RABBITSEMI-SMI DEFINITIONS ::= BEGIN IMPORTS MODULE-IDENTITY, OBJECT-IDENTITY, enterprises FROM SNMPv2-SMI; rabbitsemi MODULE-IDENTITY -- 2 dashes are the comment marker -- the information that should be here may be seen in RABBITSEMI-SMI.txt ::= { enterprises 12807 } -- assigned by IANA

The MODULE-IDENTITY macro names rabbitsemi as node 12807 under enterprises. rabbitsemiProducts OBJECT-IDENTITY STATUS current DESCRIPTION "rabbitsemiProducts is the root OBJECT IDENTIFIER from which sysObjectID values are assigned. Actual values are defined in RABBITSEMI-PRODUCTS-MIB." ::= { rabbitsemi 1 } The OBJECT-IDENTITY macro names rabbitsemiProducts as node 1 under the rabbitsemi node. Studying the rest of the definitions in this file, you should be able to create the following tree diagram:

Chapter 15: SNMP

415

enterprise (1)

. . .

rabbitsemi (12807)

. . .

Z-World Inc. (12817) rabbitsemiChipsets (9) rabbitsemiExperiments (8) rabbitsemiConfig (7)

rabbitsemiProducts (1) rabbitsemiMgmt (2) oemExperiments (3) oemAssigned (4)

rabbitsemiAgentCapability (6)

rabbitsemiModules (5)

demos (1)

processor (1)

communication (2)

15.2.5.2 Defining the Demo MIB The file RABBITSEMI-DEMO-SNMP1.txt defines another level in the MIB and then defines the leaf nodes that will hold the values of the managed objects for this demo. The leaf nodes correspond to the variable definitions in the code shown in Section 15.2.1. RABBITSEMI-DEMO-SNMP1 DEFINITIONS ::= BEGIN IMPORTS MODULE-IDENTITY, OBJECT-TYPE, NOTIFICATION-TYPE, IpAddress, TimeTicks FROM SNMPv2-SMI DisplayString FROM SNMPv2-TC demos FROM RABBITSEMI-SMI; rabbitsemiDemoSNMP1 MODULE-IDENTITY -- Look in RABBITSEMI-DEMO-SNMP1.txt for the details that belong here. ::= { demos 1 } demoRWObjects OBJECT IDENTIFIER ::= { rabbitsemiDemoSNMP1 1 } demoROObjects OBJECT IDENTIFIER ::= { rabbitsemiDemoSNMP1 2 }

416

TCP/IP Users Manual

At this point, the correspondence between 12807. 3.1.1 and SNMP_ENTERPRISE.oemExperiments.demos.rabbitsemiDemoSNMP1 becomes apparent. The remainder of RABBITSEMI-DEMO-SNMP1.txt contains definitions for the rest of the MIB that will be used in the demo. Here are the first two leaf nodes: rw-int OBJECT-TYPE SYNTAX INTEGER (-32768..32767) MAX-ACCESS read-write STATUS current DESCRIPTION "A read/write short integer value." ::= { demoRWObjects 1 0 }

rw-long OBJECT-TYPE SYNTAX INTEGER (-200000000..200000000) MAX-ACCESS read-write STATUS current DESCRIPTION "A read/write long integer value." ::= { demoRWObjects 2 0 } The OBJECT-TYPE macro defines leaf nodes on the MIB tree. The SYNTAX line defines the data type of the managed object stored at the leaf node and gives the allowable range of values.

Chapter 15: SNMP

417

The tree diagram for this demo looks like this:

rabbitsemi (12807)

rabbitsemiProducts (1)

oemExperiments (3) demos(1) rabbitsemiDemoSNMP1 (1)

rabbitsemiChipsets (9)

demoRWObjects (1) rw-int (1.0) rw-long (2.0) rw-foct (3.0) rw-str (4.0) rw-oct (5.0) rw-oid (6.0) rw-ipaddr (7.0) rw-timeticks (8.0)

demoROObjects (2) ro-int (1.0) ro-long (2.0) ro-foct (3.0) ro-str (4.0) ro-oct (5.0) ro-oid (6.0)

418

TCP/IP Users Manual

15.2.6 Running the SNMP Agent


Now that weve seen how the SNMP manager uses an SMI defined MIB to recognize the MIB controlled by the SNMP agent, lets look at the rest of the sample program SNMP1.C (our SNMP agent for this demo). After the MIB is defined, the managed objects are initialized, the MIB tree is checked to make sure it was constructed without error and the network is started. // Initialize the variables. rw_int = 1001; rw_long = 1000002; memcpy(rw_fixed, "rw_fixed abcdefghijk", 20); strcpy(rw_str, "rw_str"); memcpy(rw_oct, "\x06\x00rw_oct", 8); memcpy(&rw_oid, &_p, sizeof(snmp_oid)); trapdest_ip = aton(MANAGER_IP); rw_tt = snmp_timeticks(); r_int = 2001; r_long = 2000002; memcpy(r_fixed, "r_fixed abcdefghijkl", 20); strcpy(r_str, "r_str"); memcpy(r_oct, "\x05\x00r_oct", 7); memcpy(&r_oid, &_p, sizeof(snmp_oid)); // Finally, we check that the MIB tree was constructed without error. // If there was any error, p will be set to NULL. if (!p) { printf("There was an error constructing the MIB.\n"); exit(1); } // Monitor the rw_int variable (whose MIB tree index was saved in monindex). // trapindices was set up with the indices for r_int and r_oct. snmp_monitor(monindex, 0, 3000, 1, 16, 6, &trapdest_ip, SNMP_TRAPDEST, 30, 2, trapindices); // See what we've got. snmp_print_tree(); printf("MIB tree: used %ld out of %ld bytes\n", snmp_used(), (long)SNMP_MIB_SIZE); // Now start up the network sock_init(); // Set base epoch

Chapter 15: SNMP

419

The SNMP handler is called the same way all the other TCP/IP handlers are calledby tcp_tick(). tt = _SET_SHORT_TIMEOUT(5000); for (;;) { if (_CHK_SHORT_TIMEOUT(tt)) { #ifdef SEND_TRAPS snmp_trap(trapdest_ip, SNMP_TRAPDEST, 20, 2,trapindices); #endif tt = _SET_SHORT_TIMEOUT(5000); } tcp_tick(NULL); } } The macros _SET_SHORT_TIMEOUT and _CHK_SHORT_TIMEOUT are defined in net.lib. They are based on MS_TIMER and offer a consistent way of setting time outs of 1ms thru 32 seconds using only 16-bit arithmetic. This SNMP agent will send a trap message every 5 seconds.

15.3 Configuration Macros


These macros may be defined in the initialization code of the SNMP agent before the inclusion of dcrtcp.lib.

SNMP_DFLT_READMASK
The mask used to grant read access. The default is 0x03, which gives read access to both the private and public communities.

SNMP_DFLT_WRITEMASK
The mask used to grant write access. The default is 0x02, which gives write access to only the private community.

SNMP_INTERFACE
Specify the network interface to listen for SNMP messages. May be set to a fixed interface, or IF_ANY to listen on all interfaces. The default is IF_DEFAULT.

SNMP_TOS
Specifies the IP TOS for SNMP. The default is IPTOS_RELIABLE.

SNMP_MIN_TRAP_INTVL
Minimum interval between transmission of trap messages, specified in milliseconds. Helps prevent inadvertent network overload. Must not be more than 30,000 milliseconds. The default is 1000 ms.

420

TCP/IP Users Manual

SNMP_MAX_MONITOR
Maximum number of monitored variables. Each monitored variable requires (SNMP_MAX_MON_DATA*2) + 33 bytes of root data.

SNMP_MAX_MON_DATA
Maximum number of additional variables sent with a monitor trap. The default is 2.

SNMP_MAX_DATA
Largest size of SNMP datagram supported (input or output). This must be at least 484 bytes to conform with RFC1157. Currently, this should not be larger than the default value since outgoing fragmentation is not supported. The default value is (MIN_MTU28).

SNMP_MAX_NAME
Maximum size of an encoded object identifier (OID). The default is 32.

SNMP_MAX_STRING
The largest octet string that may be retrieved or set via SNMP. Making this larger only affects the amount of stack space used by the SNMP handler functions. It does not limit internal storage of string values in the MIB tree. The largest practical size would be a few bytes less than SNMP_MAX_DATA. The minimum allowable size is (2*SNMP_MAX_NAME). The default is 128.

SNMP_MAX_BINDINGS
The maximum number of variables supported in any one message. This has a bearing on stack space usage. Each additional binding will require 4 more bytes of stack. The default is 32.

SNMP_MAX_COMMUNITY_NAME
The maximum string length of community names (i.e., passwords). The default is 16.

SNMP_MAX_COMMUNITIES
The number of communities recognized by the SNMP agent. The default is 2, or 3 if traps are supported.

SNMP_MIB_SIZE
Defines the maximum size of the MIB tree structure resident in xmem. The default size is 4096 bytes. The default allows for about 100 objects.

SNMP_PORT
The UDP port that the agent will listen on. The default is 161.

SNMP_TRAP_PORT
The UDP port that the agent will send traps to on the SNMP manager. The default is 162.

Chapter 15: SNMP

421

SNMP_TRAPS
Must be defined in the application to support trap sending.

USE_MIB
Defining this macro is only necessary if MIB functionality is being used without SNMP.

15.4 API Functions


This section describes all of the API functions available in SNMP.LIB and MIB.LIB.

snmp_add
snmp_parms *snmp_add( snmp_parms *p, char *n, word type, void *v, word maxlen );
DESCRIPTION

Add an object into the MIB tree. The parameter structure *p must be set up using snmp_init_parms() and other functions such as snmp_set_stem() to indicate the object ID of the object to be added. This function is used to add objects which reside in root data storage. The object must persist at the specified location (v) at least until the object is deleted using snmp_delete(). Typically, the object may already exist in some preexisting application (e.g., as a field in some structure). The object may be used exactly as an ordinary variable or field, except that its value may change whenever tcp_tick() is called and there happens to have been an SNMP SET request on that object. (If SNMP is not being used, the object will not be modified by any of the MIB.LIB functions.) snmp_add() and snmp_xadd() are the most general functions. Cleaner code can result from using the equivalent macro invocations. There are 10 macro invocations of snmp_add and snmp_xadd. The macros ensure that the correct type and length parameters are passed.

422

TCP/IP Users Manual

snmp_add (continued)
The macros for snmp_add() are:

snmp_add_int(p,n,i) snmp_add_uint(p,n,i) snmp_add_long(p,n,i) snmp_add_ipaddr(p,n,i) snmp_add_timeticks(p,n,i) snmp_add_ulong(p,n,i) snmp_add_str(p,n,s,m) snmp_add_oct(p,n,s,m) snmp_add_foct(p,n,s,m) snmp_add_objectID(p,n,s)

where parameters p and n are as for this function; i is an integer or long integer address; s is a char *; and m is a maximum length.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Optional extra OID level to temporarily append to the OID in *p. If -1, this is not done. Otherwise, the level is appended; the value added; then the extra level removed. It is not possible to specify OID levels greater than 231 - 1. Type of value to add. This is a composite of the internal type (indicating the memory layout) and the type visible to SNMP agents. The possible composite types are selected from the following list:
SNMP_INTEGER_AS_SHORT SNMP_INTEGER_AS_LONG SNMP_INTEGER SNMP_OCTETSTR_VARIABLE SNMP_OCTETSTR_NULLTERM SNMP_ASCIISTR SNMP_OCTETSTR_FIXED SNMP_OBJECT_ID SNMP_IPADDR_AS_OCT SNMP_IPADDR_AS_LONG SNMP_COUNTER_AS_SHORT SNMP_COUNTER_AS_LONG SNMP_COUNTER SNMP_GAUGE_AS_SHORT SNMP_GAUGE_AS_LONG SNMP_GAUGE SNMP_TIMETICKS (SNMP_P_INTEGER<<4 | SNMP_SHORT) (SNMP_P_INTEGER<<4 | SNMP_LONG) = SNMP_INTEGER_AS_LONG (SNMP_P_OCTETSTR<<4 | SNMP_OCT) (SNMP_P_OCTETSTR<<4 | SNMP_STR) = SNMP_OCTETSTR_NULLTERM (SNMP_P_OCTETSTR<<4 | SNMP_FOCT) (SNMP_P_OID<<4 | SNMP_OID) (SNMP_P_IPADDR<<4 | SNMP_FOCT) (SNMP_P_IPADDR<<4 | SNMP_LONG) (SNMP_P_COUNTER<<4 | SNMP_SHORT) (SNMP_P_COUNTER<<4 | SNMP_LONG) = SNMP_COUNTER_AS_LONG (SNMP_P_GAUGE<<4 | SNMP_SHORT) (SNMP_P_GAUGE<<4 | SNMP_LONG) = SNMP_GAUGE_AS_LONG (SNMP_P_TIMETICKS<<4 | SNMP_LONG)

type

Chapter 15: SNMP

423

snmp_add (continued)
v Pointer to the actual object in root data storage. This storage becomes managed by SNMP/MIB, which is why it must be static. To alter the value of the object, it is permissible (in fact recommended) to simply update the object directly. Note that it is this pointer value that is stored in the MIB tree, not a copy of the object. Note that variable-length octet strings are stored in a special format: the 1st two bytes of the location are used to store the current length. The specified maximum length, maxlen, includes the length of this 2-byte prefix. The actual length of the object can thus be no more than the maxlen - 2. Maximum permissible length of the object. This is applicable to variable length objects, since SNMP needs to know the allowable size bounds for the object to avoid overwriting past the end of the allocated space for the object.

maxlen

RETURN VALUE

Returns p unless p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_set_parse_stem, snmp_append_stem, snmp_append_parse_stem, snmp_set_access, snmp_set_callback, snmp_up_stem, snmp_xadd, snmp_delete, snmp_get, snmp_last_index

424

TCP/IP Users Manual

snmp_add_community
int snmp_add_community( char *cname, byte mask );
DESCRIPTION

Add a new community with a given access mask to the table of community names. The size of the table is specified using SNMP_MAX_COMMUNITIES. The first 3 communities are automatically defined thus do not need to be added using this function.
PARAMETERS

cname

Community name as a null-terminated string with a maximum length of SNMP_MAX_COMMUNITY_NAME. This specifies the access groups (one or more of 8 groups) to which this community belongs. Three groups are predefined: SNMP_PUBLIC_MASK - public group with read-only access SNMP_PRIVATE_MASK - private group with read/write access SNMP_TRAPDEST_MASK - trap group with no access

mask

RETURN VALUE

-1: No room in table.

0: Number of entries in community table, after current addition. This is the


community index, which is required for other API functions.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_set_dflt_communities, snmp_set_community, snmp_community_name, snmp_community_mask

Chapter 15: SNMP

425

snmp_append_binary_oid
snmp_oid *snmp_append_binary_oid( snmp_oid *oid, word len, char *bname );
DESCRIPTION

Append the object ID encoded as a string of bytes to the OID currently set in *oid. This function may be used when all levels in the OID string are numbers between 0 and 255 inclusive. Each OID level is simply the binary value of each byte pointed to by bname. The number of levels (i.e., bytes) is specified by len. For example, to append "255.6.0.1" make the following call: snmp_append_binary_oid(oid, 4, "\xFF\x06\x00\x01"); This function is identical to snmp_append_binary_stem(), except that it uses an snmp_oid structure.
PARAMETERS

oid

Pointer to snmp_oid structure to set. If NULL,does nothing but return NULL. Number of bytes in bname. Pointer to first byte of OID.

len bname
RETURN VALUE

Returns oid unless the OID string is too long to fit in the snmp_oid structure in which case NULL is returned. If oid is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_append_oid, snmp_append_binary_stem, snmp_set_stem

426

TCP/IP Users Manual

snmp_append_binary_stem
snmp_parms * snmp_append_binary_stem( snmp_parms *p, word len, char *bname );
DESCRIPTION

Append the object ID encoded as a string of bytes to the OID currently set in *p. This function may be used when all levels in the OID string are numbers between 0 and 255 inclusive. Each OID level is simply the binary value of each byte pointed to by bname. The number of levels (i.e., bytes) is specified by len. For example, to append "255.6.0.1" make the following call: snmp_append_binary_stem(p, 4, "\xFF\x06\x00\x01"); This function is identical to snmp_append_binary_oid(), except that it uses an snmp_parms structure.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Number of bytes in bname. Pointer to first byte of OID.

len bname
RETURN VALUE

Returns p unless the OID string is too long to fit in the parameter structure in which case NULL is returned. If p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_append_oid, snmp_append_parse_stem, snmp_set_stem

Chapter 15: SNMP

427

snmp_append_oid
snmp_oid * snmp_append_oid( snmp_oid *oid, word len, char *eos );
DESCRIPTION

This function is identical to snmp_append_stem, except that it uses an snmp_oid structure. See documentation for snmp_set_stem() for an explanation of OID encoding.
PARAMETERS

oid

Pointer to snmp_oid structure to set. If NULL, does nothing but return NULL. Length of eos. Encoded OID string.

len eos
RETURN VALUE

Returns oid unless the OID string is too long to fit in the snmp_oid structure in which case NULL is returned. If oid is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_oid, snmp_append_parse_oid, snmp_append_stem

428

TCP/IP Users Manual

snmp_append_parse_oid
snmp_oid * snmp_append_parse_oid( snmp_oid *oid, char *name );
DESCRIPTION

Appends the specified OID string, expressed in dotted decimal format, to the OID currently set in the OID structure. This function is identical to snmp_append_parse_stem(), except that it uses an snmp_oid structure.
PARAMETERS

oid

Pointer to snmp_oid structure to set. If NULL, does nothing but return NULL. OID string in dotted decimal notation e.g., "7.5.99"

name
RETURN VALUE

Returns oid unless the OID string is too long to fit in the snmp_oid structure in which case NULL is returned. If oid is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_append_oid, snmp_append_parse_stem, snmp_set_stem

Chapter 15: SNMP

429

snmp_append_parse_stem
snmp_parms * snmp_append_parse_stem( snmp_parms *p, char *name );
DESCRIPTION

Appends the specified OID string, expressed in dotted decimal format, to the OID currently set in the parameter structure. This function is identical to snmp_append_parse_oid(), except that it uses an snmp_parms structure.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. OID string in dotted decimal notation e.g., "7.5.99"

name
RETURN VALUE

Returns p unless the OID string is too long to fit in the parameter structure in which case NULL is returned. If p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_set_parse_stem

430

TCP/IP Users Manual

snmp_append_stem
snmp_parms * snmp_append_stem( snmp_parms *p, word len, char *eos );
DESCRIPTION

Appends the encoded object identifier string to the OID already set in *p. See snmp_set_stem() for a description of OID encoding. This function is identical except that it appends rather than replaces the OID.
PARAMETERS

Pointer to parameter structure to append to. If NULL, does nothing but return NULL. Length of eos. Encoded OID string.

len eos
RETURN VALUE

Returns p unless the OID string is too long to fit in the parameter structure in which case NULL is returned. If p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_parse_stem, snmp_append_oid

Chapter 15: SNMP

431

snmp_community_mask
int snmp_community_mask( word c_index );
DESCRIPTION

Return the community access mask of the specified community.


PARAMETERS

c_index

Community table index. This is the value returned by snmp_add_community(), or may be SNMP_PUBLIC, SNMP_PRIVATE or SNMP_TRAPDEST for the predefined default communities.

RETURN VALUE

-1: The index was outside the table bounds. 0..255: The requested bit mask.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_add_community, snmp_set_dflt_communities, snmp_set_community, snmp_community_name

432

TCP/IP Users Manual

snmp_community_name
char * snmp_community_name( word c_index, int *length );
DESCRIPTION

Return the name and, optionally, the length of the specified community.
PARAMETERS

c_index

The community table index is the value returned by snmp_add_community(), or may be SNMP_PUBLIC, SNMP_PRIVATE or SNMP_TRAPDEST for the predefined default communities. If not NULL, then the addressed location will be set with the community name string length.

length

RETURN VALUE

NULL: the index was outside the table bounds. Otherwise, a pointer to the community name is returned. The data at this location should not be modified.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_add_community, snmp_set_dflt_communities, snmp_set_community, snmp_community_mask

Chapter 15: SNMP

433

snmp_copy_oid
snmp_oid * snmp_copy_oid( snmp_parms *p, snmp_oid *n );
DESCRIPTION

Copy the current object ID "stem" from *p into *n.


PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. Object ID structure to be filled in with current stem from *p. Must not be NULL.

RETURN VALUE

If p was NULL returns NULL, otherwise returns n.


LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem

434

TCP/IP Users Manual

snmp_delete
snmp_parms * snmp_delete( snmp_parms *p );
DESCRIPTION

Delete a node, or a subtree, of the MIB tree. The object ID to delete is specified in *p. All objects whose OID has a complete initial match with the specified OID will be deleted. Note that the indices which may have been retrieved for a deleted object will no longer be valid.
PARAMETERS

Pointer to parameter structure whose stem is set up with the OID to delete. If NULL, does nothing but return NULL.

RETURN VALUE

Returns p unless it is NULL on entry, then nothing is done except to return NULL. If no objects were deleted, then the function also returns NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_set_parse_stem, snmp_append_stem, snmp_append_parse_stem, snmp_up_stem, snmp_add, snmp_xadd, snmp_last_index

Chapter 15: SNMP

435

snmp_format_oid
char * snmp_format_oid ( snmp_oid *oid );
DESCRIPTION

Debugging only: format OID in dotted decimal and return static buffer.
PARAMETERS

oid
RETURN VALUE

oid to format.

Address of string in static storage.


LIBRARY

MIB.LIB

436

TCP/IP Users Manual

snmp_get
snmp_parms * snmp_get( snmp_parms *p );
DESCRIPTION

Retrieves the object whose OID is set in *p. The retrieved object information is stored back in *p, and can be examined using the snmp_last_*() series of functions.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc.

RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get_next, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

Chapter 15: SNMP

437

snmp_get_indexed
snmp_parms * snmp_get_indexed( snmp_parms *p, word i );
DESCRIPTION

Retrieves the object whose MIB tree index is given by i. The object information is stored in *p, and can be examined using the snmp_last_*() series of functions. The object ID of the retrieved object may be obtained by calling snmp_copy_oid(). The object ID is automatically set in *p, so snmp_get_next() can be called repeatedly to retrieve higher objects in ascending sequence of object ID. See documentation for snmp_last_index() for information on MIB tree indices.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. Index of object, e.g., from snmp_last_index().

i
RETURN VALUE

NULL if p was NULL, or if there is no next object. Otherwise, returns p.


LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_copy_oid, snmp_get, snmp_get_next, snmp_last_index, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

438

TCP/IP Users Manual

snmp_get_next
snmp_parms * snmp_get_next( snmp_parms *p );
DESCRIPTION

Retrieves the next object in lexicographically ascending sequence. The object information is stored in *p, and can be examined using the snmp_last_*() series of functions. The object ID of the retrieved object may be obtained by calling snmp_copy_oid(). The object ID is automatically set in *p, so this function can be called repeatedly to retrieve all objects in ascending sequence of object ID.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc.

RETURN VALUE

NULL if p was NULL, or if there is no next object. Otherwise, returns p.


LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_copy_oid, snmp_get, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

Chapter 15: SNMP

439

snmp_init_parms
snmp_parms * snmp_init_parms( snmp_parms *p );
DESCRIPTION

Initialize the parameter structure p. This is used to set *p to a known state prior to calling other functions in the MIB group. If p is not NULL, it is set to all binary zeros. The initial OID stem is then set to "43.6.1.4.1" or, if SNMP_ENTERPRISE is defined, it is set to "43.6.1.4.1.SNMP_ENTERPRISE". Note that the leading "43" is the standard compression of "1.3." The current read and write masks are set to SNMP_DEFAULT_READMASK and SNMP_DEFAULT_WRITEMASK respectively. The current index is set to "null."
PARAMETERS

Pointer to parameter structure to initialize. If NULL, does nothing but return NULL.

RETURN VALUE

Always returns p.
LIBRARY

MIB.LIB

440

TCP/IP Users Manual

snmp_last_index
word snmp_last_index( snmp_parms *p );
DESCRIPTION

Return the MIB tree index for the last object added or retrieved. Indices are the most efficient way to access objects in the MIB tree, however the efficiency comes at a price: it is possible for indices to become invalid if the snmp_delete() function is ever used. Once an object is created using snmp_add_*(), its index is guaranteed to remain valid until the same object is deleted using snmp_delete(). After such time, the index may refer to an unused tree entry (and thus be garbage) or another object may be created which will re-use the same index. It is safe to store indices of objects which are never deleted. Otherwise, the programmer must exercise caution. An index value of SNMP_NULL (which is not the same as zero!) indicates a null index e.g., "not found" or "unknown."
PARAMETERS

Parameter structure that was previously set by a call to snmp_add_*() or snmp_get() or snmp_get_next().

RETURN VALUE

SNMP_NULL if p was NULL, otherwise returns the index. The returned index may be garbage if no object was added or retrieved by previous calls.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_add, snmp_xadd, snmp_delete

Chapter 15: SNMP

441

snmp_last_int
int snmp_last_int( snmp_parms *p );
DESCRIPTION

Return the short integer value of the last object retrieved from the MIB tree. The object must be of a short integer type, and may be in either xmem or root storage. If the object is in fact a long integer, then the return value will reflect only the low 16 bits of the value. If the object is of any other type the returned value will be garbage.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

Returns the object value. Result will be garbage if the object is not a short integer type, or if p was NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

442

TCP/IP Users Manual

snmp_last_len
word snmp_last_len( snmp_parms *p );
DESCRIPTION

Return the current length of the last object retrieved from the MIB tree. The object may be of any type, and may be in either xmem or root storage. The current length may be less than or equal to the result from snmp_last_maxlen().
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

Returns the object length. Result will be garbage if p was NULL.


LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_maxlen

Chapter 15: SNMP

443

snmp_last_long
long snmp_last_long( snmp_parms *p );
DESCRIPTION

Return the long integer value of the last object retrieved from the MIB tree. The object must be of a long integer type, and may be in either xmem or root storage. If the object is of any other type (including short integer) the returned value will be garbage.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

Returns the object value. Result will be garbage if the object is not a long integer type, or if p was NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

444

TCP/IP Users Manual

snmp_last_maxlen
word snmp_last_maxlen( snmp_parms *p );
DESCRIPTION

Return the maximum length of the last object retrieved from the MIB tree. The object may be of any type, and may be in either xmem or root storage. The current length (from snmp_last_len()) may be less than or equal to the result from this function.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

Returns the maximum permissible object length. Result will be garbage if p was NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

Chapter 15: SNMP

445

snmp_last_mem
char * snmp_last_mem( snmp_parms *p );
DESCRIPTION

Return the logical address of the last object retrieved from the MIB tree. The object may be of any type, however, it must NOT have been defined as an xmem object.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

If p was NULL, or the object is in xmem storage, returns NULL. Otherwise, the logical (near) address of the object is returned.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_xmem, snmp_last_type, snmp_last_len

446

TCP/IP Users Manual

snmp_last_objectID
snmp_parms * snmp_last_objectID( snmp_parms *p, snmp_oid * oid );
DESCRIPTION

Copy the last OID object which was retrieved from the MIB tree into *oid.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next(). Pointer to an snmp_oid structure, to which the result is copied.

oid
RETURN VALUE

NULL: if p was NULL or the last object retrieved was not an object-ID object. p: otherwise.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem

Chapter 15: SNMP

447

snmp_last_snmp_type
word snmp_last_snmp_type( snmp_parms *p )
DESCRIPTION

Return the SNMP type of the last object retrieved from the MIB tree. Each object has two "types." The SNMP type indicates the type of object to external entities using SNMP to examine objects on this agent. The internal type (see snmp_last_type()) indicates the memory layout for the object in the MIB tree. The same memory layout may be used for different SNMP types, and vice versa.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

SNMP type of the object. The currently supported types are:


LIBRARY

SNMP_P_INTEGER SNMP_P_OCTETSTR SNMP_P_OID SNMP_P_IPADDR0 SNMP_P_COUNTER SNMP_P_GAUGE SNMP_P_TIMETICKS

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_type, snmp_last_len

448

TCP/IP Users Manual

snmp_last_type
snmp_type snmp_last_type( snmp_parms *p );
DESCRIPTION

Returns the internal type of the last object retrieved from the MIB tree. Each object has two "types." The SNMP type (see snmp_last_snmp_type()) indicates the type of object to external entities using SNMP to examine objects on this agent. The internal type indicates the memory layout for the object in the MIB tree. The same memory layout may be used for different SNMP types, and vice versa.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

Internal type of the object. The currently supported types are


LIBRARY

SNMP_SHORT - 16-bit integer SNMP_LONG - 32-bit integer SNMP_STR - null-terminated string SNMP_OCT - variable length binary (octet) string SNMP_FOCT - fixed length binary string SNMP_OID - Object ID

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_xmem, snmp_last_snmp_type, snmp_last_len

Chapter 15: SNMP

449

snmp_last_xmem
long snmp_last_xmem( snmp_parms *p );
DESCRIPTION

Return the physical address of the last object retrieved from the MIB tree. The object may have been defined to reside in either xmem or root data space, and may be of any type.
PARAMETERS

Parameter structure that was used previously in a call to a retrieval function such as snmp_get_indexed(), snmp_get() or snmp_get_next().

RETURN VALUE

If p was NULL, returns 0. Otherwise, returns the physical (20-bit linear) address of the object.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_get, snmp_get_next, snmp_get_indexed, snmp_last_int, snmp_last_long, snmp_last_mem, snmp_last_type, snmp_last_len

450

TCP/IP Users Manual

snmp_monitor
int snmp_monitor( word index, long minval, long maxval, word minintvl, word maxintvl, word nmesg, longword *ipaddr, word c_index, int trap_num, word noids, word *indices );
DESCRIPTION

Sets up automatic monitoring of a specified managed object. This monitors the object (which must be integer type), so that if the object goes outside the specified lower and upper bound, trap messages will be sent. This function overcomes some of the limitations of the normal snmp_trap() mechanism, in that it performs automatic retransmissions to practically ensure that the network management agent notices the condition. The managed object must exist in the MIB tree, and must not be deleted while it is being monitored. Any given object can only be monitored once. If the object is already being monitored, a call to this function with the same object (index) will change the monitor settings for that object. You must #define SNMP_TRAPS to use this function. The maximum number of different objects which may be monitored is specified by SNMP_MAX_MONITOR. When an object is monitored, it is periodically examined (at intervals of SNMP_MIN_TRAP_INTVL milliseconds). If, at the time of examination, the object is outside the specified bounds then trap message are initiated. After the first message is sent, another message will be sent minintvl seconds later. Subsequent messages are sent at doubling time intervals up to a maximum of maxintvl. A maximum of nmesg messages will be sent for any "event." The time intervals and message counters are reset as soon as the object goes back inside the specified range.

Chapter 15: SNMP

451

snmp_monitor (continued)
PARAMETERS

index

MIB tree index of the object to monitor. This value may be obtained when the object is created, by calling snmp_last_index(). Minimum allowed value of object. Maximum allowed value of object. If the object is stored with an SNMP type of SNMP_P_INTEGER, then the comparisons are done using signed arithmetic. All other SNMP types are assumed to be unsigned, so unsigned arithmetic is performed. Minimum interval, in seconds, between successive trap messages if the object goes outside the specified bounds. Maximum interval, in seconds, between messages. Maximum number of messages to send while an object is outside bounds. The message count is reset when the variable goes back inside bounds. Address of the IP address of the network management agent to which trap messages should be directed. A pointer is used for this parameter to allow sharing the same destination address between multiple monitor calls. The pointer must point to static storage. Community table index. This is the value returned by snmp_add_community(), or may be SNMP_TRAPDEST for the predefined default trap destination community. Trap number to use. This must be 0. Negative numbers are reserved for SNMP predefined trap types. Otherwise, generic traps are sent. Number of MIB tree indices in the following list (may be zero). This must be less than or equal SNMP_MAX_BINDINGS. Array of MIB tree indices. Each element in this array is the MIB tree index of an object to send with the trap message. Tree indices may be obtained using snmp_last_index() and other MIB functions.

minval maxval

minintvl

maxintvl nmesg

ipaddr

c_index

trap_num

noids

indices

452

TCP/IP Users Manual

snmp_monitor (continued)
RETURN VALUE

-1: Insufficient room in monitor table. -2: Inappropriate object specified for monitoring (i.e., it is not an integer type). This will only be returned if SNMP_DEBUG is defined, otherwise the check is not performed. 0..SNMP_MAX_MONITOR-1: The monitor table index used for this object
LIBRARY

SNMP.LIB
SEE ALSO

snmp_unmonitor, snmp_trap

Chapter 15: SNMP

453

snmp_print_tree
void snmp_print_tree( void );
DESCRIPTION

Debugging function only. Prints entire MIB tree. Leaf nodes are printed with their OID number and value. Non-leaf nodes are printed with their OID fragment suffixed with '.'. For simplicity, this function recurses.
LIBRARY

MIB.LIB

454

TCP/IP Users Manual

snmp_set_access
snmp_parms *snmp_set_access( snmp_parms *p, byte rm, byte wm );
DESCRIPTION

Set the read and write masks for access control of the next object to be added. Read/write masks are only applicable if SNMP is used. The functions in this library for accessing objects do not apply the access masks. This remains in effect for all further additions until changed by a new call to snmp_set_access(). The rm and wm are bit 8-bit bitmasks. A bit "n" is set if the communities whose access mask have the "n"th bit set are allowed to access the object in that mode (read or write). By default, bit 0 is set for the PUBLIC community's access mask and bit 1 is set for the PRIVATE community. Typically, objects are created with rm = 3 and wm = 2, giving both public and private read access, but only private has write access.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Read access mask. Write access mask.

rm wm
RETURN VALUE

Returns p unless p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms

Chapter 15: SNMP

455

snmp_set_callback
snmp_parms * snmp_set_callback( snmp_parms *p, snmp_callback cb );
DESCRIPTION

Set the callback function for the next object to be added. This remains in effect for all further additions until cancelled by passing NULL for the callback function. Use of the callback function is described in the printed documentation. It is only applicable if SNMP is being used. The functions in MIB.LIB do not invoke the callback.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Pointer to callback function, or NULL to cancel.

cb
RETURN VALUE

Returns p unless p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms

456

TCP/IP Users Manual

snmp_set_community
int snmp_set_community( word c_index, char *cname, byte mask );
DESCRIPTION

Changes the name (password string) and access mask for the community indexed by c_index.
PARAMETERS

c_index

Community table index. This is the value returned by snmp_add_community(), or may be SNMP_PUBLIC, SNMP_PRIVATE or SNMP_TRAPDEST for the predefined default communities. Community name as a null-terminated string with maximum length of SNMP_MAX_COMMUNITY_NAME. Access mask. This specifies the access groups (one or more of 8 groups) to which this community belongs. Three groups are predefined: SNMP_PUBLIC_MASK - public group with read-only access SNMP_PRIVATE_MASK - private group with read/write access SNMP_TRAPDEST_MASK - trap group with no access.

cname

mask

RETURN VALUE

-1: the supplied index was outside the table bounds. Otherwise, returns the c_index parameter.

LIBRARY

SNMP.LIB
SEE ALSO

snmp_add_community, snmp_set_dflt_communities, snmp_community_name, snmp_community_mask

Chapter 15: SNMP

457

snmp_set_dflt_communities
int snmp_set_dflt_communities( char *public, char *private, char *trapdest );
DESCRIPTION

Sets the name (i.e., password string) of the first 3 default communities. These communities are assigned the following access masks:

public: SNMP_PUBLIC_MASK - read-only access private: SNMP_PRIVATE_MASK - read/write access trapdest: SNMP_TRAPDEST_MASK - no local access, used when sending traps
to the network management agent. This function should be called once, when the application is initialized. All parameters are null-terminated strings, with a maximum length of SNMP_MAX_COMMUNITY_NAME.
PARAMETERS

public private trapdest


RETURN VALUE

Public access password. Private access password. Trap password sent with trap messages.

0
LIBRARY

SNMP.LIB
SEE ALSO

snmp_add_community, snmp_set_community, snmp_community_name, snmp_community_mask

458

TCP/IP Users Manual

snmp_set_foct
snmp_parms * snmp_set_foct( snmp_parms *p, char *s );
DESCRIPTION

Set the value of a fixed-length object. The OID of the object must be set in *p. If the object is not in fact a fixed-length binary object, then NULL will be returned and there will be no alteration of the value. s is always assumed to point to an area of storage of the required length. See snmp_set_int() for other general considerations.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. New value for the object.

s
RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID, or if the object was not stored with "foct" internal type. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get, snmp_add, snmp_xadd, snmp_set_int, snmp_set_long, snmp_set_oct, snmp_set_str, snmp_set_objectID

Chapter 15: SNMP

459

snmp_set_int
snmp_parms * snmp_set_int( snmp_parms *p, int i );
DESCRIPTION

Set the value of a short integer object. The OID of the object must be set in *p. If the object is not in fact a short integer, then NULL will be returned and there will be no alteration of the value. The object may reside in either root or xmem data space. This function only needs to be called when the address of the object itself is not known. Typically, this would be in functions which perform general processing of MIB objects. If the address of the object is known, it is far more efficient to update the object directly.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. New value for the object.

i
RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID, or if the object was not stored with short integer internal type. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get, snmp_add, snmp_xadd, snmp_set_long, snmp_set_str, snmp_set_oct, snmp_set_foct, snmp_set_objectID

460

TCP/IP Users Manual

snmp_set_long
snmp_parms * snmp_set_long( snmp_parms *p, long L );
DESCRIPTION

Set the value of a long integer object. The OID of the object must be set in *p. If the object is not in fact a long integer, then NULL will be returned and there will be no alteration of the value. See snmp_set_int() for other general considerations.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. New value for the object.

L
RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID, or if the object was not stored with long integer internal type. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get, snmp_add, snmp_xadd, snmp_set_int, snmp_set_str, snmp_set_oct, snmp_set_foct, snmp_set_objectID

Chapter 15: SNMP

461

snmp_set_objectID
snmp_parms *snmp_set_objectID( snmp_parms *p, snmp_oid *oid );
DESCRIPTION

Set the value of an object-ID object. The OID of the object must be set in *p. If the object is not in fact an OID, then NULL will be returned and there will be no alteration of the value. See snmp_set_int() for other general considerations.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. New value for the object.

oid
RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID, or if the object was not stored with object-ID internal type. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get, snmp_add, snmp_xadd, snmp_set_int, snmp_set_str, snmp_set_oct, snmp_set_foct, snmp_set_long

462

TCP/IP Users Manual

snmp_set_oct
snmp_parms * snmp_set_oct( snmp_parms *p, word len, char *s );
DESCRIPTION

Set the value of a variable-length object. The OID of the object must be set in *p. If the object is not in fact an octet string, then NULL will be returned and there will be no alteration of the value. If len is too long for the specified maximum storage length for this object, the data is truncated to fit. See snmp_set_int() for other general considerations.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. New length for the object. New value for the object. This points to the actual object data, not the 2-byte length prefix.

len s

RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID, or if the object was not stored with variable length octet string type. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get, snmp_add, snmp_xadd, snmp_set_int, snmp_set_long, snmp_set_str, snmp_set_foct, snmp_set_objectID

Chapter 15: SNMP

463

snmp_set_oid
snmp_oid * snmp_set_oid( snmp_oid *oid, word len, char *eos );
DESCRIPTION

This function is identical to snmp_set_stem(), except that it uses an snmp_oid structure. See documentation for snmp_set_stem().
PARAMETERS

oid

Pointer to snmp_oid structure to set. If NULL, does nothing but return NULL. Length of eos. Encoded OID string.

len eos
RETURN VALUE

Returns oid unless the OID string is too long to fit in the snmp_oid structure in which case NULL is returned. If oid is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_append_oid, snmp_set_parse_oid, snmp_set_stem

464

TCP/IP Users Manual

snmp_set_parse_oid
snmp_oid * snmp_set_parse_oid( snmp_oid *oid, char *name );
DESCRIPTION

This function is identical to snmp_set_parse_stem(), except that it uses an snmp_oid structure. See documentation for snmp_set_parse_stem().
PARAMETERS

oid

Pointer to snmp_oid structure to set. If it is NULL, does nothing but return NULL. OID string in dotted decimal notation e.g., "43.6.1"

name
RETURN VALUE

Returns oid unless the OID string is too long to fit in the snmp_oid structure in which case NULL is returned. If oid is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_append_oid, snmp_set_parse_stem, snmp_set_stem

Chapter 15: SNMP

465

snmp_set_parse_stem
snmp_parms * snmp_set_parse_stem( snmp_parms *p, char *name );
DESCRIPTION

If p is not NULL, set the OID stem in *p to the OID expressed in dotted decimal notation in name. This function is easier to use than snmp_set_stem(), but has the disadvantage of being less efficient. Apart from the method of expressing the OID, the semantics are identical to snmp_set_stem().
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. OID string in dotted decimal notation e.g., "43.6.1"

name
RETURN VALUE

Returns p unless the OID string is too long to fit in the parameter structure in which case NULL is returned. If p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_set_parse_oid

466

TCP/IP Users Manual

snmp_set_stem
snmp_parms *snmp_set_stem( snmp_parms *p, word len, char *eos);
DESCRIPTION

If p is not NULL, the OID stem is set to the encoded OID string specified by eos (with length len). eos must be a fully qualified OID, encoded using the internal representation (RLER). RLER encoding is performed as follows: each OID level is an unsigned number between 0 and 232-1 inclusive. Reading from left to right, each level is encoded and written left to right. If the level is less than 254, it is written as a single byte with that value. Otherwise, if it is less than 65536, it is written as 0xFE yy zz 0xFE where yy is the MSB of the 16-bit value and zz is the LSB. Otherwise the number is >= 65536 and it is written as 6 bytes: 0xFF ww xx yy zz 0xFF where ww is the MSB of the 32-bit number and zz is the LSB. The total length of the constructed string is passed in len. Note that there are other functions which provide easier ways of setting the object ID in the parameter structure. This function, and related functions, serve the purpose of setting the "current object identifier" in the parameter structure. This is necessary for other functions, such as snmp_add_int(), which need to know the applicable object identifier.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Length of eos. Encoded OID string.

len eos
RETURN VALUE

Returns p unless the OID string is too long to fit in the parameter structure in which case NULL is returned. If p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_append_stem, snmp_set_parse_stem, snmp_set_oid

Chapter 15: SNMP

467

snmp_set_str
snmp_parms * snmp_set_str( snmp_parms *p, char *s );
DESCRIPTION

Set the value of an ascii string object. The OID of the object must be set in *p. If the object is not in fact a string, then NULL will be returned and there will be no alteration of the value. If the string is too long for the specified maximum storage length for this object, then the string is truncated to fit. This may result in the object having no null terminator. See snmp_set_int() for other general considerations.
PARAMETERS

Parameter structure that was previously initialized by calls to snmp_init_parms(), snmp_set_stem() etc. New value for the object.

s
RETURN VALUE

NULL if p was NULL, or if there is no object with the given OID, or if the object was not stored with string internal type. Otherwise, returns p.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_append_stem, snmp_get_indexed, snmp_get, snmp_add, snmp_xadd, snmp_set_int, snmp_set_long, snmp_set_oct, snmp_set_foct, snmp_set_objectID

468

TCP/IP Users Manual

snmp_start
int snmp_start( void );
DESCRIPTION

Restart the SNMP subsystem after calling snmp_stop().


RETURN VALUE

0
LIBRARY

SNMP.LIB
SEE ALSO

snmp_stop

Chapter 15: SNMP

469

snmp_stop
int snmp_stop( void );
DESCRIPTION

Temporarily suspends network access to the SNMP subsystem. Incoming SNMP messages are received but ignored while in the stopped state. If the stopped state is maintained for less than about 1 second, then external agents will retransmit the request. Otherwise, they may give up. This function is used when there is a substantial amount of MIB tree processing to be performed locally, and it is also desired to prevent asynchronous access to the MIB tree (e.g., to prevent race conditions).
RETURN VALUE

0
LIBRARY

SNMP.LIB
SEE ALSO

snmp_start

470

TCP/IP Users Manual

snmp_time_since
longword snmp_time_since( longword epoch );
DESCRIPTION

Return the number of SNMP "timeticks" elapsed since a specified "epoch."


PARAMETERS

epoch

The reference epoch. This should be a value obtained by a previous call to snmp_timeticks().

RETURN VALUE

Number of 1/100 second intervals since "epoch". This value counts from 0 to 231-1, then wraps around to zero.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_timeticks

Chapter 15: SNMP

471

snmp_timeticks
longword snmp_timeticks( void );
DESCRIPTION

Return the current SNMP "timeticks" count.


RETURN VALUE

Number of 1/100 second intervals since the application started. This value counts from 0 to 231-1, then wraps around to zero.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_time_since

472

TCP/IP Users Manual

snmp_trap
int snmp_trap( longword ipaddr, word c_index, int trap_num, word noids, word *indices );
DESCRIPTION

Send an SNMPv1 trap message. Traps are unsolicited messages sent to a network management agent, for example to inform the agent about an unusual condition. Traps are not delivered reliably, i.e., the message may be lost in the network. There is no acknowledgement of trap receipt by the agent. You must #define SNMP_TRAPS to use this function.
PARAMETERS

ipaddr c_index

IP address of network management agent. Community table index. This is the value returned by snmp_add_community(), or may be SNMP_TRAPDEST for the predefined default trap destination community. Trap number to use. This must be 0. Negative numbers are reserved for SNMP predefined trap types. Otherwise, generic traps are sent. Number of MIB tree indices in the following list (may be zero). This must be less than or equal SNMP_MAX_BINDINGS. Array of MIB tree indices. Each element in this array is the MIB tree index of an object to send with the trap message. Tree indices may be obtained using snmp_last_index() and other MIB functions.

trap_num

noids

indices

RETURN VALUE

-1: error, trap not sent because there was an error constructing the message (probably because too many or too long variables were specified), or because the message could not be sent using UDP. Otherwise, length of constructed message returned.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_monitor

Chapter 15: SNMP

473

snmp_unmonitor
int snmp_unmonitor( word index );
DESCRIPTION

Stop monitoring the object that was previously monitored by snmp_monitor(). This function must be used if the object being monitored is to be deleted from the MIB tree. You must #define SNMP_TRAPS to use this function.
PARAMETERS

index
RETURN VALUE

MIB tree index of the object to unmonitor.

-1: the object is not currently being monitored. Otherwise returns the monitor table index.
LIBRARY

SNMP.LIB
SEE ALSO

snmp_monitor, snmp_trap

474

TCP/IP Users Manual

snmp_up_oid
snmp_oid * snmp_up_oid( snmp_oid *oid, word levels );
DESCRIPTION

This function is identical to snmp_up_stem, except that it uses an snmp_oid structure. See documentation for snmp_up_stem().
PARAMETERS

oid

Pointer to snmp_oid structure to set. If NULL, does nothing but return NULL. Number of levels to truncate on right of current OID. If this is greater than the current number of levels, the OID is set to empty.

levels

RETURN VALUE

Returns oid unless NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_up_stem

Chapter 15: SNMP

475

snmp_up_stem
snmp_parms * snmp_up_stem( snmp_parms *p, word levels );
DESCRIPTION

Truncate the last n levels in the OID currently set in *p. This move "up" towards the first level in the OID.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Number of levels to truncate on right of current OID. If this is greater than the current number of levels, the OID is set to empty.

levels

RETURN VALUE

Returns p unless p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem

476

TCP/IP Users Manual

snmp_used
long snmp_used( void );
DESCRIPTION

Obtain information about the amount of memory used by the MIB tree. The value returned may be used as the setting for SNMP_MIB_SIZE if the application does not dynamically add objects during normal execution.
RETURN VALUE

Number of bytes of xmem currently used by the MIB tree.


LIBRARY

MIB.LIB

Chapter 15: SNMP

477

snmp_xadd
snmp_parms * snmp_xadd( snmp_parms *p, char *n, word type, long xs, word maxlen );
DESCRIPTION

This function is identical to snmp_add(), except that the object resides in xmem storage. Instead of a void * address, an xmem (20-bit linear) address is stored. In common with snmp_add(), there is also a set of macros, the use of which may result in cleaner code. The macro names are identical to those for snmp_add, except that the names all start with "snmp_xadd.
PARAMETERS

Pointer to parameter structure to set. If NULL, does nothing but return NULL. Optional extra OID level to temporarily append to the OID in *p. If -1, this is not done. Otherwise, the level is appended; the value added; then the extra level removed. It is not possible to specify OID levels greater than 231-1. Type of value to add. See description in snmp_add(). xmem address of the actual object in xmem data storage. The same considerations apply to this address as they do for the near pointers used by snmp_add(). Maximum permissible length of the object.

type xs

maxlen
RETURN VALUE

Returns p unless p is NULL on entry, then nothing is done except to return NULL.
LIBRARY

MIB.LIB
SEE ALSO

snmp_init_parms, snmp_set_stem, snmp_set_parse_stem, snmp_append_stem, snmp_append_parse_stem, snmp_set_access, snmp_set_callback, snmp_up_stem, snmp_add, snmp_delete, snmp_get, snmp_last_index

478

TCP/IP Users Manual

16. Telnet
The library, Vserial.lib, implements the telecommunications network interface, known as telnet. The implementation is a telnet-to-serial and serial-to-telnet gateway. This chapter is divided into two parts. The first part describes the library from Dynamic C version 7.05 and later. The second part describes the library prior to 7.05.

16.1 Telnet (Dynamic C 7.05 and later)


This implementation is more general than the previous one. Any of the four serial ports can be used and other I/O streams can be added. Multiple connections are supported by the use of unique gateway identifiers.

16.1.1 Setup
To use a serial port, the circular buffers must be initialized. For instance, if serial port A is used by an application, then the following macros must be defined in the program: #define AINBUFSIZE #define AOUTBUFSIZE 31 31

It might be necessary to have bigger buffers for some applications. 16.1.1.1 Low-Level Serial Routines A table to hold the low-level I/O routines must be defined as type VSerialSpec. typedef struct { int id; int (*open)(); int (*close)(); int (*tick)(); int (*rdUsed)(); int (*wrFree)(); int (*read)(); int (*write)(); } VSerialSpec; // unique ID to match with calls to listen/open // serial port routines, or // serial port compatible routines.

For each serial port (A, B, C and D), there is a pre-defined macro in VSERIAL.LIB: #define VSERIAL_PORTA(id) { (id), serAopen, serAclose, NULL, serArdUsed, serAwrFree, serAread, serAwrite } The parameter passed to VSERIAL_PORTA is the unique gateway identifier mentioned earlier. This value is chosen by the developer when entries are made to the array of type VSerialSpec (also known as the spec table).

Chapter 16: Telnet

479

16.1.1.2 Configuration Macros

VSERIAL_DEBUG
Turns on debug messages.

VSERIAL_NUM_GATEWAYS
The number of telnet sessions must be defined and must match the number of entries in the spec table.

16.1.2 API Functions (Dynamic C 7.05 and later)


The following functions compose the latest telnet API. A sample program demonstrating their use is available at Samples\tcpip\telnet\vserial.c.

vserial_close
int vserial_close( int id );
DESCRIPTION

Closes the specified gateway. This will not only terminate any network activity, but will also close the serial port.
PARAMETERS

id
RETURN VALUE

ID of the gateway to change, as specified in the spec table.

0: Success. 1: Failure.
LIBRARY

VSERIAL.LIB

480

TCP/IP Users Manual

vserial_init
int vserial_init ( void );
DESCRIPTION

Initializes the daemon and parses the spec table.


RETURN VALUE

0: Success; 1: Failure.
LIBRARY

VSERIAL.LIB

Chapter 16: Telnet

481

vserial_keepalive
int vserial_keepalive ( int id, long timeout );
DESCRIPTION

This function sets the keepalive timer to generate TCP keepalives after timeout periods of inactivity. This helps detect if the connection has gone bad. Keepalives should be used at the application level, but if that is not possible, then timeout should be set so as to not overload the network. The standard timeout is two hours, and should be set sooner than that only for a Very Good Reason.
PARAMETERS

id timeout

Unique gateway identifier. Number of seconds of inactivity allowed before a TCP keepalive is sent. A value of 0 shuts off keepalives.

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

VSERIAL.LIB

482

TCP/IP Users Manual

vserial_listen
int vserial_listen( int id, long baud, int port, long remote_host, int flags );
DESCRIPTION

Listens on the specified port for a telnet connection. The gateway process is started when a connection request is received. On disconnect, re-listen happens automatically.
PARAMETERS

id baud

ID of the gateway to change, as specified in the spec table. The parameter to send to the open() serial port command; its usually the baud rate. The local TCP port to listen on. The remote host from whom to accept connections, or 0 to accept a connection from anybody. Option flags for this gateway. Currently the only valid bit flags are VSERIAL_COOKED to strip out telnet control codes, or 0 to leave it a raw data link.

port remote_host

flags

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

VSERIAL.LIB

Chapter 16: Telnet

483

vserial_open
int vserial_open( int id, long baud, int port, long remote_host, int flags, long retry );
DESCRIPTION

Opens a connection to a remote host and maintains it, starting the gateway process.
PARAMETERS

id baud

ID of the gateway to change, as specified in the spec table. The parameter to send to the open() serial port command; its usually the baud rate. The TCP port on the remote host to connect to. The remote host to connect to. Option flags for this gateway. Currently the only valid bit flags are VSERIAL_COOKED to strip out telnet control codes, or 0 to leave it a raw data link. The retry time-out, in seconds. When a connection fails, or if the connection was refused, we will wait this number of seconds before retrying.

port remote_host flags

retry

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

VSERIAL.LIB

484

TCP/IP Users Manual

vserial_tick
int vserial_tick( void );
DESCRIPTION

Runs the telnet daemon - must be called periodically.


RETURN VALUE

0: Success; 1: Failure. But call it periodically no matter the return value! An error message can be seen when 1 is returned if you define VSERIAL_DEBUG at the top of your program.
LIBRARY

VSERIAL.LIB

Chapter 16: Telnet

485

16.2 Telnet (pre-Dynamic C 7.05)


The API available for telnet changed with Dynamic C version 7.05. This is the old API

16.2.1 Configuration Macros SERIAL_PORT_SPEED


The baud rate of the serial port. Defaults to 115,200 bps.

TELNET_COOKED
#define this to have telnet control codes stripped out of the data stream. This is useful if you are actually telneting to the device from another box. It should not be defined if you are using two devices as a transparent bridge over the Ethernet.

16.2.2 API Functions

telnet_init
int telnet_init( int which, longword addy, int port );
DESCRIPTION

Initializes the connection. This function must not be called by an application program starting with Dynamic C 7.05.
PARAMETERS

which

Is one of the following: TELNET_LISTENListens on a port for incoming connections. TELNET_RECONNECTConnects to a remote host, and reconnects if the connection dies. TELNET_CONNECTConnects to a remote host, and terminates if the connection dies.

addy port

IP address of the remote host, or 0 if we are listening. Port to bind to if we are listening, or the port of the remote host to connect to.

RETURN VALUE

0: Success. 1: Failure.
LIBRARY

VSERIAL.LIB

486

TCP/IP Users Manual

telnet_tick
int telnet_tick( void );
DESCRIPTION

Must be called periodically to run the daemon.


RETURN VALUE

0: Success (call it again); 1: Failure; TELNET_CONNECT died, or a fatal error occurred.


LIBRARY

VSERIAL.LIB

telnet_close
void telnet_close( void );
DESCRIPTION

Terminates any connections currently open, and shuts down the daemon.
LIBRARY

VSERIAL.LIB

Chapter 16: Telnet

487

16.2.3 An Example Telnet Server


The following code implements a telnet server. It listens on well-known port 23 for a connection request. Data is passed transparently via serial port C. #define #define #define #define MY_IP_ADDRESS "10.10.6.105" MY_NETMASK "255.255.255.0" MY_GATEWAY "10.10.6.19" MY_NAMESERVER "10.10.6.19" // Set serial port speed. // This is a raw data port.

#define SERIAL_PORT_SPEED 115200 #undef TELNET_COOKED #memmap xmem #use "dcrtcp.lib" #use "vserial.lib" #define SERVER_PORT 0 main() { sock_init();

// Defaults to port 23. // Initialize stack. // Initialize server // Run server; this is non-blocking // Error, close telnet connection

telnet_init(TELNET_LISTEN,0,SERVER_PORT); while(!telnet_tick()) continue; telnet_close(); }

488

TCP/IP Users Manual

16.2.4 An Example Telnet Client


This sample code implements a client that can connect to the above telnet server. #define #define #define #define MY_IP_ADDRESS "10.10.6.106" MY_NETMASK "255.255.255.0" MY_GATEWAY "10.10.6.19" MY_NAMESERVER "10.10.6.19" // Must match server.

#define SERIAL_PORT_SPEED 115200 #undef TELNET_COOKED #memmap xmem #use "dcrtcp.lib" #use "vserial.lib" #define SERVER_PORT 0 main() { sock_init();

// Defaults to port 23; must match server.

#define REM_HOST "10.10.6.19" // Remote IP to connect to. // Initialize the stack

// Tell the server to connect and reconnect if the connection is lost telnet_init(TELNET_RECONNECT,resolve(REM_HOST),SERVER_PORT); while(!telnet_tick()) continue; telnet_close(); } // Run client; this is non-blocking // Error, close telnet connection

Chapter 16: Telnet

489

490

TCP/IP Users Manual

17. General Purpose Console


The library, zconsole.lib, implements a serial-based console that we call Zconsole. It can be used to:

Configure a board. Upload and download web pages. Change web page variables without re-uploading the page. Send e-mail. Calls subsystem initialization for ARP, TCP, UDP and DNS (if applicable).

17.1 Zconsole Features


Recognizing that embedded control systems are wide-ranging in their requirements, zconsole.lib was designed with flexibility and extensibility in mind. Designers can choose the available functionality they want and leave the rest alone. Zconsole includes:

Login name and password protection. Default and custom Zconsole commands. Default and custom error messages. Help text for Zconsole commands, including custom commands Multiple I/O streams that can be used simultaneously. A fail-safe backup system for configuration data.

17.1.1 File System Requirement


Prior to Dynamic C 7.30, an application program using Zconsole must include the lines: #use "filesystem.lib" // If using the improved file system available with // Dynamic C 7.05, substitute fs2.lib for filesystem.lib #use "zconsole.lib" Using the file system is no longer necessary.

17.1.2 TCP/IP and Zconsole


Dynamic C TCP/IP functionality may be used by a Zconsole application program by including the statement #use dcrtcp.lib in the program. Other TCP/IP protocols may be added with #use statements of the appropriate libraries.

Chapter 17: General Purpose Console

491

17.2 Login Name and Password


There is a sample program, Samples\tcpip\LOGINCONSOLE.C, that demonstrates the use of the login name/password functionality for Zconsole. Zconsole command functions: con_loginname(), con_loginpassword() and con_logout() are described in Section 17.4.1.1 starting on page 495. The structure that saves the name and password information can be backed up using the backup macro CONSOLE_BACKUP_LOGIN. Please see Section 17.7 starting on page 516 for details on the backup system.

17.3 Zconsole Commands and Messages


Zconsole is a command-driven application. A command is issued either at the keyboard using a terminal emulator or a command is generated and sent from an attached machine. Zconsole carries out the command, and either the message OK \r\n is returned, or an error is returned in the form of: ERROR XXXX This is an error message.\r\n Note that the carriage return and new line characters (\r\n) are always returned by Zconsole whether the command completed successfully or not.

17.3.1 Zconsole Command Data Structure


The command system is set up at compile time with an array of ConsoleCommand structures. There is one array entry for each command recognized by Zconsole. typedef struct { char *command; int (*cmdfunc)(); long helptext; } ConsoleCommand

command
This field is a string like the following: SET MAIL FROM. That is, each word of the command is separated by a space. The case of the command does not matter. Entering this string is how the command is invoked.

cmdfunc
This field is a function pointer to the function that implements the command. The functions that come with Zconsole are listed in Section 17.4.1.1 on page 495.

helptext
This field points to a text file. The text file contains help information for the associated command. When HELP COMMAND is entered, this text file (the help information for COMMAND) will be printed to Zconsole. The help text comes from #ximported text files.

492

TCP/IP Users Manual

17.3.1.1 Help Text for General Cases


There are two cases in Zconsole.lib where help text is needed, but is not associated with a particular command. It is still necessary to allocate a ConsoleCommand structure to access the help text. The first case is the help overview given when HELP is entered by itself. The command field should be and the cmdfunc field should be NULL. { "", NULL, help_txt }, The second case is HELP SET. This is an overview of the family of SET commands, i.e., commands that set configuration values. For HELP SET, the command field should be SET and the cmdfunc field should be NULL. { "SET", NULL, help_set_txt }, This second case illustrates the general case of displaying help for a family of commands. The family name can not be the name of a command.

Chapter 17: General Purpose Console

493

17.4 Zconsole Command Array


An array of ConsoleCommand structures must be defined in an application program as a constant global variable named console_commands[]. All commands available at the console, those provided in Zconsole.lib and custom commands, must have an entry in this array.

17.4.1 Zconsole Commands


The following is an example of a list of commands that may be defined in a Zconsole application. When the command name {i.e., the string in the command field) is received by the console, the function pointed to in the cmdfunc field is executed. When the console receives the command, HELP <command name>, the text file located at physical address helptext will be displayed.
const ConsoleCommand console_commands[] = { { "HELLO WORLD", hello_world, 0 }, { "ECHO", con_echo, help_echo_txt }, { "HELP", con_help, help_help_txt }, { "", NULL, help_txt }, { "SET", NULL, help_set_txt }, { "SET PARAM", con_set_param, 0 }, { "SET IP", con_set_ip, help_set_txt }, { "SET NETMASK", con_set_netmask, help_set_txt }, { "SET GATEWAY", con_set_gateway, help_set_txt }, { "SET NAMESERVER", con_set_nameserver, help_set_txt }, { "SET MAIL", NULL, help_set_mail_txt }, { "SET MAIL SERVER", con_set_mail_server, help_set_mail_server_ txt }, { "SET MAIL FROM", con_set_mail_from, help_set_mail_from_txt }, { "SHOW", con_show, help_show_txt }, { "PUT", con_put, help_put_txt }, { "GET", con_get, help_get_txt }, { "DELETE", con_delete, help_delete_txt }, { "LIST", NULL, help_list_txt }, { "LIST FILES", con_list_files, help_list_txt }, { "LIST VARIABLES", con_list_variables, help_list_txt }, { "CREATEV", con_createv, help_createv_txt }, { "PUTV", con_putv, help_putv_txt }, { "GETV", con_getv, help_getv_txt }, { "MAIL", con_mail, help_mail_txt }, { "RESET FILES", con_reset_files, 0 } { "RESET VARIABLES, con_reset_variables, help_reset_variables } };

494

TCP/IP Users Manual

17.4.1.1 Default Command Functions


The following functions are provided in Zconsole.lib. Each one takes a pointer to a ConsoleState structure as its only parameter, following the prototype for custom functions described in Section 17.4.1.2 on page 500. Each of these functions return 0 when it has more processing to do (and thus will be called again), 1 for successful completion of its task, and -1 to report an error. Parameters needed by the commands using these functions are passed on the command line.

con_add_nameserver()
This function adds a name server to the list of name servers (unlike con_set_nameserver() that clears the list of name servers and adds one name server). A command that use this function takes one parameter: the IP address of the name server in dotted quad notation.

con_createv()
This function creates a variable that can be used with SSI commands in SHTML files. Certain SSI commands can be replaced by the value of this variable, so that a web page can be dynamically altered without re-uploading the entire page. Note, however, that the value of the variable is not preserved across power cycles, although the variable entry is still preserved. That is, the value of the variable may change after a power cycle. It can be changed again, though, with a putv command. It works in the following fashion (if the command is called CREATEV): usage: "createv <varname> <vartype> <format> <value> [strlen]" A web variable that can be referenced within web files is created. <varname> is the name of the variable <vartype> is the type of the variable (INT8, INT16, INT32, FLOAT32, or STRING) <format> is the printf-style format specifier for outputting the variable (such as "%d") <value> is the value to assign the variable. [strlen] is only used if the variable is of type STRING. It is used to give the maximum length of the string.

con_delete()
This function deletes a file from the file system. A command that uses this function takes one parameter: the name of the file to delete.

con_echo()
This function turns on or off the echoing of characters on a particular I/O stream. That is, it does not affect echoing globally, but only for the I/O stream on which it is issued. A command that uses this function takes one parameter: ON | OFF.

Chapter 17: General Purpose Console

495

con_get()
This function displays a file from the file system. It works in the following fashion (if the command is called GET):

ASCII mode: usage: "get <filename>"


The file is then sent, followed by the usual OK message.

BINARY mode: usage: "get <filename> <size in bytes>"


The message "LENGTH <len>" will be sent, indicating length of the file to be sent, and then the file will be sent, but not more than <size in bytes> bytes.

con_getv()
This function displays the value of the given variable. The variable is displayed using the printfstyle format specifier given in the createv command. A command that uses this function takes one parameter: the name of the variable.

con_help()
This function implements the help system for Zconsole. A command that uses this function takes one parameter: the name of another command. Zconsole outputs the associated help text for the requested command. The help text is the text file referenced in the third field of the ConsoleCommand structure.

con_list_files()
This function lists the files in the file system and their file sizes. A command that uses this function takes no parameters.

con_list_variables()
This function displays the names and types of all variables. A command that uses this function takes no parameters.

con_loginname()
This function stores an identifier that will be remembered across power cycles (with batterybacked RAM). The existence of the identifier will be used to prompt the user of a new console session. Before console access to the controller is allowed, a valid identifier must be entered in response to the prompt. A command that uses this function takes one parameter: an identifier that will be used as the login name.

496

TCP/IP Users Manual

con_loginpassword()
This function stores an identifier that will be remembered across power cycles (with batterybacked RAM). The existence of the identifier will be used to prompt the user for a password after a login name has been entered. Before console access to the controller is allowed, a valid identifier must be entered in response to the prompt. A command that uses this function takes no parameters on the command line, but requires a series of user inputs in response to prompts. In the following screen shot, the command is named login password, and is typed in by the user. All other screen text shown here was printed by Zconsole.

If no identifier is stored for the password, a <CR> must be sent in response to the prompt for the old password.
NOTE: A login name must be stored by a command using con_loginname()for a login password to be applicable, i.e., if a password has been stored but no login name, new console sessions will not prompt for the password or a login name. If a login name is applicable, but there is no password, new console sessions will prompt for the login name and grant access after a valid name is entered without prompting for a password.

con_logout()
This function exits the current console session and begins a new session by entering the initialization state of Zconsole. A command that uses this function takes no parameters.

con_mail()
This function sends e-mail to the server specified by con_mail_server(), with the return address specified by set_mail_from(). A command that uses this function takes one parameter: the destination e-mail address. If the command is named mail, the usage is: "mail destination@where.com" The first line of the message will be used as the subject, and the other lines are the body. The body is terminated with a ^D or ^Z (0x04 or 0x1A).

Chapter 17: General Purpose Console

497

con_put()
This function creates a new file in the file system for use with the HTTP server. It works in the following fashion (if the command is called PUT):

ASCII mode: usage: "put <filename>"


The file is then sent, terminating with a ^D or ^Z (0x04 or 0x1A).

BINARY mode: usage: "put <filename> <size in bytes>"


The file is then sent, and must be exactly the specified number of bytes in length. Note that ASCII mode is only useful for text files, since the console will ignore non-displayable characters. In binary mode, the put command will time out after CON_TIMEOUT seconds of inactivity (60 by default).

con_putv()
This function updates the value of a variable. A command that uses this function takes two parameters: the name of the variable, and the new value for the variable.

con_reset_files()
This function removes all web files.

con_reset_variables()
This function removes all web variables.

con_set_dhcp()
This function turns DHCP configuration for an interface "on" or "off." Currently this command only works with the default interface. After DHCP has been turned on, ZConsole will undertake reacquiring the lease should it be dropped. (For example, a lease might be dropped if the DHCP server is unavailable for an extended period of time.)

con_set_gateway()
This function changes the gateway of the board. A command that uses this function takes one parameter: the new gateway in dotted quad notation, e.g., 192.168.1.1.

con_set_icmp_config()
This function configures an interface to use directed ICMP echo request (ping) packets for configuration. A command that uses this function takes two parameters. The first is "on" or "off" to turn this feature on or off. The second parameter is optional, and specifies the intended interface (ETH0 or ETH1). Only non-PPPoE Ethernet may be used for ping configuration.

con_set_icmp_config_reset()
Normally, when an interface has been configured via a directed ping packet, further configuration via a directed ping packet is disabled (until the next power cycle). This function allows the interface to be configured via a ping packet again. A command that uses this function takes an optional interface argument (ETH0 or ETH1).

con_set_ip()
This function changes the IP address of the board. A command that uses this function takes one parameter: the new IP address in dotted quad notation, e.g., 192.168.1.112.
498 TCP/IP Users Manual

con_set_param()
This function sets the parameter for the current I/O device. Depending on the I/O device, this value could be a baud rate, a port number or a channel number. A command that uses this function takes one parameter: the value for the I/O device parameter.

con_set_mail_from()
This function sets the return address for all e-mail messages. This address will be added to the outgoing e-mail and should be valid in case the e-mail needs to be returned. A command that uses this function takes one parameter: the return address.

con_set_mail_server()
This functions identifies the SMTP server to use. A command that uses this function takes one parameter: the IP address of the SMTP server.

con_set_nameserver()
This function changes the name server for the board. A command that uses this function takes one parameter: the IP address of the new name server in dotted quad notation, e.g., 192.168.1.1.

con_set_netmask()
This function changes the netmask of the board. A command that uses this function takes one parameter: the new netmask in dotted quad notation, e.g., 255.255.255.0.

con_set_tcpip_debug()
This function is intended to aid in development and debugging. A command that uses this function takes one parameter: the numerical level of debugging messages. The higher the number, the more verbose the TCP/IP debugging messages will be.

con_show()
This function displays the current configuration of the board (IP address, netmask, and gateway). If the developers application has configuration options she would like to show other than the IP address, netmask, and gateway, she will probably want to implement her own version of the show command. The new show command can be modelled after con_show() in ZConsole.lib. A command that uses this function takes no parameters.

con_show_multi()
Like the con_show() function, this function shows the current console configuration. This command will, however, show more network configuration than is available via con_show(). Interface-specific configuration information is separated out. A command that uses this function takes an optional parameter (ETH0, ETH1, PPP0, PPP1, PPP2, etc.) to display the interface specific configuration for the specified interface. If the optional parameter is missing, the current console configuration for all valid interfaces is displayed.

Chapter 17: General Purpose Console

499

17.4.1.2 Custom Zconsole Commands


Developers are not limited to the default commands. A custom command is easy to add to Zconsole; simply create an entry for it in console_commands[]. The three fields of this entry were described in Section 17.3.1. The first field is the name of the command. The second field is the function that implements the command. This function must follow this prototype: int function_name ( ConsoleState *state ); The parameter passed to the function is a structure of type ConsoleState. Some of the fields in this structure must be manipulated by your custom command function, other fields are used by Zconsole.lib and must not be changed by the your program. typedef struct { int console_number; ConsoleIO *conio; int state; int laststate; char char char char command[CON_CMD_SIZE]; *cmdptr; buffer[CON_BUF_SIZE]; *bufferend;

// Use for reading in data. // Use for reading in data.

ConsoleCommand *cmdspec; int sawcr; int sawesc; int echo; // Check if echo is enabled, or change it. int substate; unsigned int error; int numparams; // Number of parameters on command line. int commandparams; // Number of commands issued on cmd line char cmddata[CON_CMD_DATA_SIZE]; #ifndef CON_NO_FS_SUPPORT FileNumber filenum; File file; #endif int spec; long timeout; } ConsoleState; #endif To accomplish its tasks, the function should use state->substate for its state machine (which is initialized to zero before dispatching the command handler), and state->command to read out the command buffer (to get other parameters to the command, for instance). In case of error, the function should set state->error to the appropriate value. The buffer at state->cmddata is available for the command to preserve data across invocations of the commands state machine. The size of the buffer is adjustable via the CON_CMD_DATA_SIZE macro (set to 16 bytes by default). Generally this buffer area will be cast into a data structure appropriate for the given command state machine.
500 TCP/IP Users Manual

// File processing not needed with DC 7.30 // Use for file processing. // Use for file processing. // Use for working with Zserver entities // Use for extending the time out.

Both state->numparams and state->commandparams are read-only. The latter was introduced in Dynamic C 7.30. It indicates the number of arguments in the command line that are NOT part of the command name itself. For instance, for the command SET IP 10.10.6.112 ETHO state->commandparams would be 2, but state->numparams would be 4. This distinction is made to allow the commands in Zconsole to be insensitive to the number of words that make up the name of the command itself, but still maintain backwards compatibility with custom commands that use state->numparams. The function that implements the custom command should return 0 when it has more processing to do (and thus will be called again), 1 for successful completion of its task, and -1 to report an error. The third and final field of the console_commands[] entry is the physical address of the help text file for the custom command in question. This file must be #ximported, along with all of the default command function help files that are being used. IMPORTANT: The fields discussed in the previous paragraph and the fields that have comments in the structure definition are the only ones that an application program should change. The other fields must not be changed.

17.4.2 Zconsole Error Messages


ZCONSOLE.LIB provides a list of default error messages for the default Zconsole commands. An application program must define an array for these error messages, as well as for any custom error messages that are desired. To include only the default error messages, the following array is sufficient: const ConsoleError console_errors[] = { CON_STANDARD_ERRORS // includes all default error messages }

Chapter 17: General Purpose Console

501

17.4.2.1 Default Error Messages


These are the error codes for the default error messages and the text that will be displayed by the console if the error occurs. #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define #define CON_ERR_TIMEOUT CON_ERR_BADCOMMAND CON_ERR_BADPARAMETER CON_ERR_NAMETOOLONG CON_ERR_DUPLICATE CON_ERR_BADFILESIZE CON_ERR_SAVINGFILE CON_ERR_READINGFILE CON_ERR_FILENOTFOUND CON_ERR_MSGTOOLONG CON_ERR_SMTPERROR CON_ERR_BADPASSPHRASE CON_ERR_CANCELRESET CON_ERR_BADVARTYPE CON_ERR_BADVARVALUE CON_ERR_NOVARSPACE CON_ERR_VARNOTFOUND CON_ERR_STRINGTOOLONG CON_ERR_NOTAFILE CON_ERR_NOTAVAR CON_ERR_COMMANDTOOLONG CON_ERR_BADIPADDRESS CON_ERR_INVALIDPASSWORD CON_ERR_BADIFACE CON_ERR_BADNETWORKPARAM 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

502

TCP/IP Users Manual

#define CON_STANDARD_ERRORS \ {CON_ERR_TIMEOUT, "Timed out." },\ {CON_ERR_BADCOMMAND, "Unknown command." },\ {CON_ERR_BADPARAMETER, "Bad or missing parameter." },\ {CON_ERR_NAMETOOLONG, "Filename too long." },\ {CON_ERR_DUPLICATE, "Duplicate object found." },\ {CON_ERR_BADFILESIZE, "Bad file size." },\ {CON_ERR_SAVINGFILE, "Error saving file." },\ {CON_ERR_READINGFILE, "Error reading file." },\ {CON_ERR_FILENOTFOUND, "File not found." },\ {CON_ERR_MSGTOOLONG, "Mail message too long." },\ {CON_ERR_SMTPERROR, "SMTP server error." },\ {CON_ERR_BADPASSPHRASE, "Passphrases do not match!" },\ {CON_ERR_CANCELRESET, "Reset cancelled." },\ {CON_ERR_BADVARTYPE, "Bad variable type." },\ {CON_ERR_BADVARVALUE, "Bad variable value." },\ {CON_ERR_NOVARSPACE, "Out of variable space." },\ {CON_ERR_VARNOTFOUND, "Variable not found." },\ {CON_ERR_STRINGTOOLONG, "String too long." },\ {CON_ERR_NOTAFILE, "Not a file." },\ {CON_ERR_NOTAVAR, "Not a variable." },\ {CON_ERR_COMMANDTOOLONG, "Command too long." },\ {CON_ERR_BADIPADDRESS, "Bad IP address." }, {CON_ERR_INVALIDPASSWORD, "Invalid Password.", },\ {CON_ERR_BADIFACE, "Bad interface name." },\ {CON_ERR_BADNETWORKPARAM, "Error setting network parameter."}

17.4.2.2 Custom Error Messages


Developers can create their own error messages by following the format of the default error messages. The error code numbers should be greater than 1,000 to save room for expansion of built-in error messages. #define NEW_ERROR 1001 const ConsoleError console_errors[] = { CON_STANDARD_ERRORS, // includes all default error messages { NEW_ERROR, "Any error message I want." } } The default error messages should be included in console_errors[] along with any custom error messages that are used since the commands that come with Zconsole.lib each expect their own particular error message.

Chapter 17: General Purpose Console

503

17.5 Zconsole I/O Interface


Multiple I/O methods are supported, as well as the ability to add custom I/O methods. An array of ConsoleIO structures must be defined in the application program and named console_io[]. This structure holds handlers for common I/O functions for the I/O method. typedef struct { long param; int (*open) (); void (*close)(); int (*tick) (); int (*puts) (); int (*rdUsed) (); int (*wrUsed) (); int (*wrFree) (); int (*read) (); int (*write) (); } ConsoleIO; // Baud for serial, port for telnet, etc.

17.5.1 How to Include an I/O Method


Each supported I/O method is determined at compile time, i.e., each supported I/O method must have an entry in console_io[].

17.5.2 Predefined I/O Methods


Several predefined I/O methods are in Zconsole.lib. They will be included by entering their respective macros in console_io[]. const ConsoleIO console_io[] = { CONSOLE_IO_SERA(baud rate), CONSOLE_IO_SERB(baud rate), CONSOLE_IO_SERC(baud rate), CONSOLE_IO_SERD(baud rate), CONSOLE_IO_SP(channel number), CONSOLE_IO_TELNET(port number), } The macros expand to the appropriate set of pre-defined handler functions, e.g., #define CONSOLE_IO_SERA(param) { param, serAopen, serAclose, NULL, conio_serAputs, serArdUsed, serAwrUsed, serAwrFree, serAread, serAwrite}

17.5.2.1 Serial Ports


There are predefined I/O methods for all four of the serial ports on a Rabbit board. The baud rate is set by passing it to the macro. See above.

17.5.2.2 Telnet
Zconsole runs a telnet server. The port number is passed to the macro CONSOLE_IO_TELNET. The user telnets to the controller that is running the console.

504

TCP/IP Users Manual

17.5.2.3 Slave Port


The Rabbit slave port is an 8-bit bidirectional data port. Zconsole runs on the slave processor. Two drivers are needed.

17.5.2.3.1 Slave Port Driver


The slave port driver is implemented by SLAVE_PORT.LIB. For an application to use the slave port:

The driver must be installed by including the library in the program. A call to SPinit(mode) must be made to initialize the driver. A function to process Zconsole commands sent to the slave port must be provided.
The slave port has 256 channels, separate port addresses that are independent of one another. A handler function for each channel that is used must be provided. For details on how to do this, please see the Dynamic C Users Manual. A stream-based handler, SPShandler(), to process Zconsole commands for the slave is provided in SP_STREAM.LIB. The handler is set up automatically by the console when the slave port I/O method is included. The macro, CONSOLE_IO_SP, expands to the I/O functions defined in SP_STREAM.LIB.

17.5.2.3.2 Master Connected to Rabbit Slave Port


The master controller board can be another Rabbit processor or something else. The master also needs a driver for its end of the slave port connection. An example of the software needed on the master is given in MASTER_SERIAL.LIB. The software on the master controller is, of course, specific to the task at hand. In the example driver provided, most of the work is done by the slave, making minimal changes necessary to the code on the master.

17.5.2.4 Custom I/O Methods


To define a custom I/O method, you must add a structure of type ConsoleIO to console_io[]. This structure holds the common handler functions for the I/O method. The tick function may have a NULL pointer, but the rest of the function pointers must be valid pointers to functions.

17.5.3 Multiple I/O Streams


Each I/O method has its own state machine in Zconsole. That means that each I/O method is independent of the others and they can all be used simultaneously. This imposes the important restriction that all command handlers be able to run simultaneously on different I/O streams or support proper locking for functions that cannot be performed simultaneously.

Chapter 17: General Purpose Console

505

17.6 Zconsole Execution


Normally, Zconsole will communicate over a serial link. The physical connection will differ slightly from board to board. Basically, you will need a 3 wire (GND, RXD, TXD) serial cable. Several initialization steps must be taken at the beginning of an application program to execute the console.

17.6.1 File System Initialization


Prior to Dynamic C 7.30, Zconsole depended on the flash file system included with Dynamic C. There are actually two file systems: FS1 was the first Dynamic C file system. The second one, FS2 (introduced with Dynamic C 7.05), is an improved file system. Besides defining the macro that directs the file system to EEPROM memory and including the appropriate library, i.e., #define FS_FLASH #use "filesystem.lib" // If using the improved file system available with // Dynamic C 7.05, substitute fs2.lib for filesystem.lib the application program must initialize the file system with a call to fs_init(). Starting with Dynamic C 7.30 none of this is necessary because Zconsole saves configuration information to the User block. See the Rabbit 2000 Microprocessor Users Manual or the Rabbit 3000 Microprocessor Users Manual for more information about the User block.

17.6.2 Serial Buffers


If the pre-defined serial I/O methods are used, the circular buffers used for I/O data can be resized from their default values of 31 bytes by using macros. For example, if CONSOLE_IO_SERIALC is included in console_io[], then lines similar to the following can be in the application program: #define CINBUFSIZE 1023 #define COUTBUFSIZE 255 In general, these buffers can be smaller for slower baud rates, but must be larger for faster baud rates.

17.6.3 Using TCP/IP


To use the TCP/IP functionality of Zconsole you must have the following line in your application program: #use dcrtcp.lib If you are serving web pages you must also include http.lib, and if you are sending e-mail you must include smtp.lib.

506

TCP/IP Users Manual

17.6.4 Required Zconsole Functions


To run the console, the following two functions are required.

console_init
int console_init( void );
DESCRIPTION

This function will initialize Zconsole data structures. It must be called before console_tick() is called for the first time. This function also loads the configuration information from the file system.
RETURN VALUE

0: Success; 1: No configuration information found. <0: Indicates an error loading the configuration data; -1 indicates an error reading the 1st set of information, -2 the 2nd set, and so on.
LIBRARY

zconsole.lib

console_tick
void console_tick( void );
DESCRIPTION

This function needs to be called periodically in an application program to allow Zconsole time for processing.
LIBRARY

zconsole.lib

Chapter 17: General Purpose Console

507

17.6.5 Useful Zconsole Function


Most of the following functions are only useful for creating custom commands.

con_backup
int con_backup( void );
DESCRIPTION

This function backs up the current configuration.


RETURN VALUE

0: Success 1: Failure
LIBRARY

zconsole.lib
SEE ALSO

con_backup_reserve, con_load_backup

con_backup_bytes
long con_backup_bytes( void );
DESCRIPTION

Returns the number of bytes necessary for each backup configuration file. Note that enough space for two of these files needs to be reserved. This function is most useful when ZCONSOLE.LIB is being used with FS2.LIB.
RETURN VALUE

Number of bytes needed for a backup configuration file.


LIBRARY

zconsole.lib
SEE ALSO

con_backup_reserve

508

TCP/IP Users Manual

con_backup_reserve
void con_backup_reserve( void );
DESCRIPTION

Reserves space for the configuration information in the file system. For more information on the file system see the Dynamic C Users Manual.
LIBRARY

zconsole.lib
SEE ALSO

con_backup, con_load_backup, con_backup_bytes

con_chk_timeout
int con_chk_timeout( unsigned long timeout );
DESCRIPTION

Checks whether the given timeout value has passed.


RETURN VALUE

0: Timeout has not passed !0: Timeout has passed


LIBRARY

zconsole.lib
SEE ALSO

con_set_timeout

Chapter 17: General Purpose Console

509

con_load_backup
int con_load_backup( void );
DESCRIPTION

Loads the configuration from the file system.


RETURN VALUE

0: Success 1: No configuration information found <0: Failure -1: error reading 1st set of information -2: error reading 2nd set of information, and so on
LIBRARY

zconsole.lib
SEE ALSO

con_backup, con_backup_reserve

con_reset_io
void con_reset_io( void );
DESCRIPTION

Resets all I/O methods by calling close() and open() on each of them.
LIBRARY

zconsole.lib

510

TCP/IP Users Manual

con_set_backup_lx
void con_set_backup_lx( FSLXnum backuplx );
DESCRIPTION

Sets the logical extent (LX) that will be used to store the backup configuration data. For more information on the file system see the Dynamic C Users Manual. This is only useful in conjunction with FS2.LIB. This should be called once before console_init(). Care should be taken that enough space is available in this logical extent for the configuration files. See con_backup_bytes() for more information.
PARAMETER

backuplx
LIBRARY

LX number to use for backup

zconsole.lib
SEE ALSO

con_set_files_lx, con_backup_bytes

con_set_files_lx
void con_set_files_lx( FSLXnum fileslx );
DESCRIPTION

Sets the logical extent (LX) that will be used to store files. For more information on the file system see the Dynamic C Users Manual. This is only useful in conjunction with FS2.LIB. This should be called once before console_init().
PARAMETER

fileslx
LIBRARY

LX number to use for files.

zconsole.lib
SEE ALSO

con_set_backup_lx

Chapter 17: General Purpose Console

511

con_set_user_idle
void con_set_user_idle( void (*funcptr)() );
DESCRIPTION

Sets a user-defined function that will be called when the console (for a particular I/O channel) is idle. The user-defined function should take an argument of type ConsoleState* .
LIBRARY

zconsole.lib
SEE ALSO

con_set_user_timeout

con_set_timeout
unsigned long con_set_timeout( unsigned int seconds );
DESCRIPTION

Returns the value that MS_TIMER should have when the number of seconds given have elapsed.
LIBRARY

zconsole.lib
SEE ALSO

con_chk_timeout

512

TCP/IP Users Manual

con_set_user_timeout
void con_set_user_timeout( void (*funcptr)() );
DESCRIPTION

Sets a user-defined function that will be called when a timeout event has occurred. The user-defined function should take an argument of type ConsoleState*.
LIBRARY

zconsole.lib
SEE ALSO

con_set_user_idle

console_disable
void console_disable( int which );
DESCRIPTION

Disable processing for the designated console in the console_io[] array. This function, along with console_enable(), allows the sharing of the Zconsole port with some other processing.
PARAMETER

which
LIBRARY

The console to disable.

zconsole.lib
SEE ALSO

console_init, console_enable

Chapter 17: General Purpose Console

513

console_enable
void console_enable( int which );
DESCRIPTION

Enable processing for the designated console in the console_io[] array. This function, along with console_disable(), allows the sharing of the Zconsole port with some other processing.
PARAMETER

which
LIBRARY

The console to enable.

zconsole.lib
SEE ALSO

console_init, console_disable

514

TCP/IP Users Manual

17.6.6 Zconsole Execution Choices


Zconsole can be used interactively with a terminal emulator or by sending commands from a program running on a device connected to the controller that is running the console.

17.6.6.1 Terminal Emulator


To manually enter Zconsole commands from a keyboard and view results in the Stdio window you must: 1. Run Dynamic C 7.05 or later. 2. Open a terminal emulator. Windows HyperTerminal comes with Windows. It does not work with binary files, only ASCII. Tera Term can handle both ASCII and binary. It is available for free download at http://hp.vector.co.jp/authors/VA002416/teraterm.html 3. Configure the terminal emulator as follows: COM port: (1 or 2) to which 3-wire serial cable is connected Baud Rate: 57,600 bps Data Bits: 8 Parity: None Stop Bits: 1 Flow Control: None The terminal emulator should now accept Zconsole commands. To avoid losing a <LF> at the beginning of a file when using the con_put command function, select Setup->Terminal from the Tera Term menu and set the Transmit option to CR+LF. This option might be located elsewhere if you are using a different terminal emulator.

Chapter 17: General Purpose Console

515

17.7 Backup System


Zconsole can save configuration parameters to the file system or, starting with Dynamic C 7.30, to the User block. The configuration is then available across power cycles. The backup process is done by con_backup(). Unlike the other Zconsole command functions, con_backup() does not take a parameter and it returns 0 if the backup was successful and 1 if it was not. This function is called by several of the Zconsole command functions that change configuration parameters, or that add or delete files or variables from the file system. Caution is advised when calling con_backup() since it writes to flash memory.

17.7.1 Data Structure for Backup System


The developer must define an array called console_backup[] of ConsoleBackup structures. typedef struct { void *data; int len; void (*postload)(); void (*presave)(); } ConsoleBackup;

data
This is a pointer to the data to be backed up.

len
This is how many bytes of data need to be backed up.

postload
This is a function pointer to a function that is called after configuration data is loaded, in case the developer needs to do something with the newly loaded configuration data.

presave
This is a function pointer that is called just before the configuration data is saved so that the developer can fill in the data structure to be saved. The functions referenced by postload() and presave() should have the following prototype: void my_preload(void *dataptr); The dataptr parameter is the address of the configuration data (the same as the data pointer in the ConsoleBackup structure).

516

TCP/IP Users Manual

17.7.2 Array Definition for Backup System


const ConsoleBackup console_backup[] = { CONSOLE_BASIC_BACKUP, // echo state, baud rate/port number CONSOLE_TCPIP_BACKUP, CONSOLE_TCP_MULTI_BACKUP, CONSOLE_HTTP_BACKUP, CONSOLE_SMTP_BACKUP, CONSOLE_BACKUP_LOGIN, { my_data, my_data_len, my_preload, my_presave } }

CONSOLE_BASIC_BACKUP
Causes backup of the echo state (on or off), baud rate and port number information.

CONSOLE_TCPIP_BACKUP
Causes backup of the IP addresses of the controller board and the IP address of its netmask, gateway and name server. Note that only one of the CONSOLE_TCP_* structures should be used.

CONSOLE_TCP_MULTI_BACKUP
Using this structure causes ifconfig() to save and restore network configuration. In addition to the information saved by CONSOLE_TCP_BACKUP, multiple name servers, DHCP configuration, ICMP (Ping) configuration, and multiple interface configuration are all saved by CONSOLE_TCP_MULTI_BACKUP. Some built-in console functions are for use with CONSOLE_TCP_MULTI_BACKUP. In general, except for backwards compatibility issues, CONSOLE_TCP_MULTI_BACKUP should be used instead of CONSOLE_TCP_BACKUP. Note that only one of the CONSOLE_TCP_* structures should be used.

CONSOLE_HTTP_BACKUP
Causes backup of the files and variables visible to the HTTP server.

CONSOLE_SMTP_BACKUP
Causes backup of the mail configuration.

CONSOLE_BACKUP_LOGIN
Causes backup of the ConsoleLogin structure which stores the login name and password strings.

Chapter 17: General Purpose Console

517

17.8 Zconsole Macros


Many macros are available to change the behavior of Zconsole. They are all listed here. Starting with Dynamic C 7.30 additional macros are available to support saving configuration information to the User block, DHCP, ping configuration, and multiple interfaces.

CON_BACKUP_FILE1
The file number used for the first backup file. For FS1, this number must be in the range 128-143, so that fs_reserve_blocks() can be used to guarantee free space for the backup files. Defaults to 128 for FS1. Defaults to 254 for FS2.

CON_BACKUP_FILE2
Same as above, except this is for the second backup file. Two files are used so that configuration information is preserved even if the power cycles while configuration data is being saved. For FS1, this number must be in the range 128-143. Defaults to 129 for FS1. Defaults to 255 for FS2.

CON_BACKUP_USER_BLOCK
Defaults to not defined. If this is defined, then configuration information for the console will be saved to the User block instead of to the flash file system. Note that the configuration is only safe in the case of power failures with a version 3 or higher System ID block.

CON_BUF_SIZE
Changes the size of the data buffer that is allocated for each I/O method. If the baud rate or transfer speed is too great for the console to keep up, then increasing this value may help avoid dropped characters. It is allocated in root data space. It defaults to 1024 bytes.

CON_CMD_SIZE
Changes the size of the command buffer that is allocated for each I/O method. This limits the length of a command line. It is allocated in root data space. Defaults to 128 bytes.

CON_CMD_DATA_SIZE
Default is 16. Adjusts the size of the user data area within the state structure so that user commands may preserve arbitrary information across calls. The user data area is allocated in root data space.

CON_DHCP_ACQUIRE_RETRY_TIMEOUT
Defaults to 120 seconds. If DHCP is enabled, then Zconsole will maintain the DHCP lease. This macro specifies the number of seconds after which a DHCP lease has been dropped that the board will attempt to reacquire the lease. Note that in the normal course of operation, a lease will never be dropped. Generally, that will only happen if the DHCP server is inoperable for an extended period of time (subject to the lengths of the leases that the DHCP server issues).

518

TCP/IP Users Manual

CON_HELP_VERSION
This macro should be defined if the developer wants a version message to be displayed when the HELP command is issued with no parameters. If this macro is defined, then the macro CON_VERSION_MESSAGE must also be defined.

CON_INIT_MESSAGE
Defines the message that is displayed on all Zconsole I/O methods upon startup. Defaults to Console Ready\r\n.

CON_MAIL_BUF_SIZE
Maximum length of a mail message. Defaults to 1024.

CON_MAIL_FROM_SIZE
Maximum length of mail from address to NULL terminator. Default to 51.

CON_MAIL_SERV_SIZE
Maximum length of mail server name and NULL terminator. Defaults to 51.

CON_MAX_NAME
Default is 10: maximum number of characters for a login name. This value must be equal to or less than CON_CMD_DATA_SIZE.

CON_MAX_PASSWORD
Default is 10: maximum number of characters for a login password.

CON_NO_FS_SUPPORT
This macro is defined by default only if no filesystem libraries have been used. Even if a filesystem library has been used, this can still be explicitly defined by the user. When this is defined, then the console will not save configuration information to the filesystem, and no filesystem function calls will be included.

CON_SP_RDBUF_SIZE
Size of the slave port read buffer. Defaults to 255.

CON_SP_WRBUF_SIZE
Size of the slave port write buffer. Defaults to 255.

CON_TIMEOUT
Adjusts the number of seconds that the console will wait before cancelling the current command. The timeout can be adjusted in user code in the following manner: state->timeout = con_set_timeout(CON_TIMEOUT); This is useful for custom user commands so that they can indicate when something meaningful has happened on the console (such as some data being successfully transferred).

Chapter 17: General Purpose Console

519

CON_VAR_BUF_SIZE
Adjusts the size of the variable buffer, in which values of variables can be stored for use with the HTTP server. It is allocated in xmem space. Defaults to 1024 bytes.

CON_VERSION_MESSAGE
This defines the version message to display when the HELP command is issued with no parameters. It is not defined by default, so has no default value.

520

TCP/IP Users Manual

17.9 Sample Program


The sample program Samples\zconsole\tcpipconsole.c demonstrates many of the features of zconsole.lib. Among the features this application supports is network configuration, uploading web pages, changing variables for use with web pages, sending mail, and access to the console through a telnet client. Please note that all libraries needed by zconsole.lib must be included with #use statements before the #use statement for the Zconsole library. The following code is taken from tcpipconsole.c.

/* * Size of the buffers for serial port C. If you want to use another serial port, you should * change the buffer macros below appropriately (and change the console_io[] array below). */ #define CINBUFSIZE 1023 #define COUTBUFSIZE 255 /* * Maximum number of connections to the web server. This indicates the number of sockets * that the web server will use. */ #define HTTP_MAXSERVERS 2 /* * Maximum number of sockets this program can use. The web server is taking two sockets: * the mail client uses one socket, and the telnet interface uses the other socket. */ #define MAX_SOCKETS 4 /* * All web server content is dynamic, so we do not need http_flashspec[]. */ #define HTTP_NO_FLASHSPEC /* * The file system that the console uses should be located in flash. */ #define FS_FLASH /* * The function prototype for a custom command must be declared before the * console_command[] array. */ int hello_world ( ConsoleState *state);

Chapter 17: General Purpose Console

521

The following code is for Zconsole configuration.

/* * The number of console I/O streams that this program supports. Since we are supporting * serial port C and telnet, there are two I/O streams. */ #define NUM_CONSOLES 2 /* * If this macro is defined, then the version message will be shown with the help command, * when the help command has no parameters. */ #define CON_HELP_VERSION /* * Defines the version message that will be displayed in the help command if * CON_HELP_VERSION is defined. */ #define CON_VERSION_MESSAGE "TCP/IP Console Version 1.0\r\n" /* * Defines the message that is displayed on all I/O channels when the console starts. */ #define CON_INIT_MESSAGE CON_VERSION_MESSAGE /* * The ximport directives include the help texts for the console commands. Having the help text * in xmem helps save root code space. */ #ximport "samples\zconsole\tcpipconsole_help\help.txt" help_txt ... /* The rest of the #ximport statements may be seen in tcpipconsole.c. */

522

TCP/IP Users Manual

The following code sets up all the data structures needed by the console. /* * * * The console will be available to the I/O streams given in the following array. The I/O streams are defined through macros as documented in Section 17.5.2. The parameter for the first macro represents the initial baud rate for serial port C. The second macro is passed the port number for telnet. If you change the number of I/O streams, update NUM_CONSOLES above.*/

const ConsoleIO console_io[] = { CONSOLE_IO_SERC(57600), CONSOLE_IO_TELNET(23) }; /* * * * * * * * * This array defines the commands that are available in the console. The first parameter for the ConsoleCommand structure is the command specification, i.e., how the console recognizes a command. The second parameter is the function to call when the command is recognized. The third parameter is the location of the #ximported help file for the command. Note that the second parameter can be NULL, which is useful if help information is needed for something that is not a command (like for the "SET" command below--the help file for "SET" contains a list of all of the set commands). Also note the entry for the command "", which is used to set up the help text that is displayed when the help command is used by itself (that is, with no parameters).*/

const ConsoleCommand console_commands[] = { { "HELLO WORLD", hello_world, 0 }, { "ECHO", con_echo, help_echo_txt }, { "HELP", con_help, help_help_txt }, { "", NULL, help_txt }, { "SET", NULL, help_set_txt }, { "SET PARAM", con_set_param, help_set_param_txt }, ... }; /* This array sets up the error messages that can be generated. CON_STANDARD_ERRORS is * a macro that expands to the standard errors used by the built-in commands in zconsole.lib. * Users can define their own errors here, as well.*/ const ConsoleError console_errors[] = { CON_STANDARD_ERRORS }; /* * * * * * This array defines the information (such as configuration) that will be saved to the file system. Note that if, for example, the HTTP or SMTP related commands are included in the console_commands array above, then the backup information must be included in this array. The entries below are macros that expand to the appropriate entry for each set of functionality. Users can also add their own information to be backed up here by adding more ConsoleBackup structures.*/

const ConsoleBackup console_backup[] = { CONSOLE_BASIC_BACKUP, CONSOLE_TCP_BACKUP, CONSOLE_HTTP_BACKUP, CONSOLE_SMTP_BACKUP };

Chapter 17: General Purpose Console

523

The following code defines the MIME types that the web server will handle.

const HttpType http_types[] = { { ".shtml", "text/html", shtml_handler}, // ssi { ".html", "text/html", NULL}, // html { ".gif", "image/gif", NULL}, { ".jpg", "image/jpeg", NULL}, { ".jpeg", "image/jpeg", NULL}, { ".txt", "text/plain", NULL} }; The function for the custom command is defined here and the main program finishes up the program. To see the complete sample, look in Samples\zconsole\tcpipconsole.c. /* * * * * This is a custom command. Custom commands always take a ConsoleState* as an argument (a pointer to the state structure for the given I/O stream), and return an int. The return value should be 0 when the command wishes to be called again on the next console_tick(), 1 when the command has successfully finished processing, or -1 when the command has finished due to an error.*/

int hello_world(ConsoleState *state){ state->conio->puts("Hello, World!\r\n"); return 1; } void main(void){ /* Initialize TCP/IP, clients, servers, and I/O prior to using any console functions.*/ sock_init(); tcp_reserveport(80); http_init(); // Start a listen queue and disable the 2MSL wait .

if (fs_init(0, 64)) printf("Filesystem not present!\n"); if (console_init() != 0) { printf("Console did not initialize!\n"); fs_format(0, 64, 1); /* After the file system has been initialized or formatted, space must be reserved in * the file system for the backup information. */ con_backup_reserve(); con_backup(); // Save the backup information to the console. } while (1) { console_tick(); http_handler(); } }

524

TCP/IP Users Manual

Chapter 17: General Purpose Console

525

526

TCP/IP Users Manual

18. PPP Driver


The PPP packet driver1 is a set of libraries in Dynamic C that allows the user to establish a PPP (Point-to-Point Protocol) link over a full-duplex serial line between a Rabbit-based controller and another system that supports PPP. You may also establish PPP links over Ethernet (PPPoE). The PPP driver is an add-on module that may be purchased from our website: www.zworld.com. A common use of the PPP protocol is the transfer of IP packets between a remote host and an Internet Service Provider (ISP) over a modem connection. The PPP packet driver supports the transfer of Internet Protocol (IP) data and is compatible with all TCP/IP libraries for the Rabbit. Starting with Dynamic C 7.30, the method of establishing PPP links has become easier and more flexible. Unlike previous releases, you can have as many different PPP interfaces as you have available serial (and Ethernet) ports. You can also run PPP (over serial and/or Ethernet) at the same time as ordinary non-PPPoE Ethernet. PPP performance has also dramatically improved in version 7.30.

18.1 PPP Libraries


The PPP driver is in three library files.

PPP.LIB
Contains routines to handle the link negotiation (LCP), authentication (PAP) and IP negotiation (IPCP). These are the three main sub-protocols of PPP. PPP.LIB calls routines in the other two libraries to handle the lower level (physical) layer. Starting with 7.30 there are no application-callable functions in any of the PPP libraries, however there are some functions remaining for backwards compatibility. From 7.30, PPP is mainly controlled via the ifconfig() function and friends.

PPPLINK.LIB
Contains handlers for the asynchronous serial physical layer, namely the interrupt service routine for transmitting and receiving characters over the serial link. It also handles the insertion and detection of escape characters and CRC generation and checking.

PPPOE.LIB
Contains handlers for the PPPoE physical layer, which is mainly the access concentrator discovery mechanism, and the addition of the PPPoE header to Ethernet packets. This library calls the Ethernet driver library to handle the Ethernet physical layer.

1. Prior to Dynamic C version 7.30, the PPP packet driver was derived from source code written by Darby Corporate Solutions (DCS). The source code was replaced (i.e., completely rewritten) by Z-World software engineering for Dynamic C 7.30.
Chapter 18: PPP Driver 527

A fourth library, MODEM.LIB, contains functions for controlling an external modem through a full RS232 link. Starting with Dynamic C 7.30, MODEM.LIB should not be required for most ISP connections, since most ISPs these days auto-detect the use of PPP and do not require any special logon screen navigation. Basic dial-up to an ISP is handled directly by ifconfig() settings, which do not require any special modem control (providing that your modem has a Hayes-compatible interface). MODEM.LIB is not directly related to PPP. It allows ASCII strings to be sent to and received from the modem. Typically, these strings are AT commands and modem responses. If you have special requirements for establishing communications with an ISP that cannot be handled by the default PPP library methods, you will need to explicitly include MODEM.LIB and write a program to establish the communications link. The program will typically need to command the modem to dial out; wait for a valid connection; send a user ID and password to the ISP and validate the response. After this has completed successfully, PPP can be started using the ifup() function (for 7.30 and above) or PPPinit() (for pre 7.30). NOTE: MODEM.LIB is currently limited to controlling a single modem. The modem serial port and control lines are defined using macro constants, which should match with the definitions of the PPP interface. The sample program samples\ppp\modem_test.c shows the general idea for using MODEM.LIB.

18.2 Operation Details for PPP over Serial


The first step is to configure whatever transport medium will be used for the PPP connection. For directly connecting a serial line to the peer, the two serial data lines TX and RX may be adequate. The most common situation, however, will be some sort of modem.

18.2.1 The Modem Interface


The interface between a modem and a controller is either a true RS232 interface or a variation on RS232 that uses TTL voltage levels for all of the signals. The latter are used by board-mounted modem modules. If an external modem is used, an RS232 transceiver chip is needed to convert RS232 voltages to logic signals and vice versa. A full RS232 connection has 3 outputs and 5 inputs from the controllers point of view. In RS232 terminology, the controller is referred to as the DTE (Data Terminal Equipment). Modems and other peripherals are referred to as DCEs (Data Communications Equipment). The specifics of a dial-up PPP connection are dependent on the modem hardware and the ISP.

528

TCP/IP Users Manual

18.2.1.1 Rabbit Pin Connections to Modem


The modem control library, MODEM.LIB, defines default connections to the Rabbit as follows:
Table 6. Rabbit Pin Assignments for Modem Connection RS232 Signal Rabbit Pin Direction

DTR RTS CTS DCD RI DSR TD RD 18.2.2 Flow Control

PB6 PB7 PB0 PB2 PB3 PB4 PC2 PC3

out out in in in in out in

Hardware flow control is implemented for the Rabbit PPP system. It follows the RS232 convention of using Ready To Send (RTS) and Clear To Send (CTS) lines.

18.2.2.1 Pre 7.30


Flow control is usually required for baud rates above 9600. Flow control can be enabled or disabled by PPPflowcontrolOn()and PPPflowcontrolOff(), respectively. Flow control is off by default.

18.2.2.2 Version 7.30


Flow control is not required for speeds up to and including 115200 bps. The internal character processing is fast enough that the controller does not have to throttle incoming data flow. However, the modem or peer may need to throttle transmitted data. It is recommended that the RTS (modem to controller) line be connected for modems that cannot handle a continuous data stream at the specified rate. You can also connect the CTS (controller to modem) line, but the controller will merely assert this line continuously. To enable or disable hardware flow control, call ifconfig() with the IFS_PPP_FLOWCONTROL parameter identifier. You should also specify IFS_PPP_RTSPIN and IFS_PPP_CTSPIN parameter identifiers.

Chapter 18: PPP Driver

529

18.3 Operation Details for PPPoE


PPPoE avoids most of the complexities of PPP over serial. This is because the hardware (Ethernet) is easy to set up, and no modems are involved. Actually, you might have something called a DSL modem (or similar), but this type of modem does not have to do dial-up in the usual sense. For Dynamic C versions prior to 7.30, you specify that PPPoE is to be used by defining the symbol PPPOE before including dcrtcp.lib. In addition, you have to define PKTDRV to be ppp.lib, otherwise normal Ethernet will be used. Starting with Dynamic C 7.30, PPPoE is selected by defining the symbol USE_PPPOE to be a non-zero value. Currently, the only value supported is 1 with 2 reserved for future controller boards that have a second Ethernet chip. If you define USE_PPPOE, then you should also define IFCONFIG_PPPOE0 to contain initialization options passed to ifconfig(). When PPPoE is specified, the interface is referred to by IF_PPPOE0. (IF_PPPOE1 is reserved for future boards.)

18.4 Link Control Protocol Options


Link Control Protocol is the first sub-protocol used on a PPP link. The following LCP options are supported by the Rabbit PPP system:
Table 7. Configuration Options LCP Configuration Option Type Field Meaning of Option Type

01 02 03 05 07 08

MRU (Maximum-Receive-Unit) ACCM (Async-Control-Character-Map) Auth (Authentication-Type): PAP only Magic Number PFC (Protocol-Field-Compression) ACFC (Address-and-Control-Field-Compression)

For more information on these options, refer to RFC 1661: The Point-to-Point Protocol (PPP) at: http://www.faqs.org/rfcs/rfc1661.html

530

TCP/IP Users Manual

18.5 Configuring PPP (pre 7.30)


The following parameters must be defined at compile time. At compile time, the selection between PPP and Ethernet must be made, since only one type of interface is supported at run-time. Define the following symbol if PPPoE is to be used. If it is not defined, PPP over asynchronous serial will be used: #define PPPOE The following define sets the TCP/IP stack to use PPP. This is required for either serial or PPPoE: #define PKTDRV "ppp.lib" In the most common case, the Rabbit will be dialing into an ISP. The ISP will usually wish to assign the IP address. Setting the IP address to 0.0.0.0 indicates that the Rabbit does not have a valid address when started. If the Rabbit has a permanent address or will be dialed into, MY_IP_ADDRESS should be set to a proper IP address: #define MY_IP_ADDRESS "0.0.0.0" This is a parameter intended for Ethernet and other shared network schemes. Since PPP is a single point-to-point link, all traffic must be routed through a peer. There is no such thing as local traffic. A netmask of 255.255.255.255 causes all addresses to be routed to: #define MY_NETMASK "255.255.255.255" This is the address of the host that will perform routing for the Rabbit. (With PPP this is always the peer.) If the ISP assigns a gateway machine to use, then define MY_GATEWAY to that. If the gateway is not known, defining PPP_PEERROUTE will make a gateway out of whatever machine you connect to, i.e., the Rabbit will use whatever address the peer uses when identifying itself during PPP negotiation. PPP_PEERROUTE will work under most circumstances, but a static gateway address may be needed for special cases: #define MY_GATEWAY "10.1.1.1" This works the same as with Ethernet: it defines a host that will resolve names into IP addresses: #define MY_NAMESERVER "10.1.1.2"

18.5.1 Using a Modem with PPP


This section is only relevant if you need to use a modem to dial out to an ISP (or accept dial-ins). Otherwise, if you have a hard-wired connection between the controller board and, say, a PC then you can skip this section. The first stage in dial-up PPP is to establish a modem connection with the ISP. Starting with version 7.30, the TCP/IP library will handle the most common cases for modem dial-out to an ISP. Versions prior to 7.30, or cases where the ISP connection process is non-standard, require MODEM.LIB functions to be called prior to starting the PPP interface. The function ModemInit() opens the serial port, then detects if there is a modem connected and ready. It does this by sending AT to the modem a set number of times until it receives an OK response. This should work with any Hayes-compatible modem, which is the standard today. At this point
Chapter 18: PPP Driver 531

the modem is ready and commands can be sent to it using ModemSend(). Remember to include a carriage return \r at the end of each command sent. The function ModemExpect() is used to wait for a character sequence to occur. Normally the first use of this in a program is to determine that the modem has connected. When a connection occurs, the modem will send a string along the lines of CONNECT AT x or something similar. ModemExpect() can be set to listen for this. Once connected, the ISP may either attempt PPP negotiation immediately, or request a user name and password first. In the latter case, a sequence of ModemSend() and ModemExpect() calls are used to handle this (see See Authentication on page 532). Eventually the ISP will begin PPP negotiation. At this stage ModemClose() should be called to shutdown normal serial operation. For versions prior to 7.30, after calling sock_init() and doing any other necessary TCP/IP initialization, PPPinit() is called, followed by any necessary PPP option initialization, and finally a call to PPPstart(). Once the PPP connection is established through a successful call to PPPstart(), the user can send packets to the peer using the TCP/IP libraries. Starting with version 7.30, PPPinit() and PPPstart() should not be called, since sock_init() will automatically perform the necessary PPP negotiations.

18.5.2 Selecting a Serial Port


By default the PPP link is established using serial port C. It can be changed, but it requires some #define changes near the top of PPPLINK.LIB in the section starting with PPP_SERDR. If a modem is used, some rewriting of MODEM.LIB is also required.

18.5.3 IP Addresses
When the Rabbit and the peer are establishing a connection, they negotiate what their IP addresses will be. When the Rabbit is connecting to an ISP, an IP address will be assigned to it by the ISP. In some cases, such as the Rabbit acting as a dial-in ISP, IP addresses for the Rabbit and the peer should be set by the Rabbit. This is done using PPPnegotiateIP().

18.5.4 Authentication
The PPP library supports an optional authentication phase. Both the authentication of a peer and being authenticated by a peer are done using Password Authentication Protocol (PAP). This is a simple two-way handshake only done upon initial link establishment. The most common case is when the Rabbit must authenticate itself to the ISP it is connecting to. This is configured using PPPsetAuthenticatee(), which sets the username and password the Rabbit will use.

532

TCP/IP Users Manual

A different situation arises when the Rabbit needs to authenticate a connecting peer. This is necessary when the Rabbit is being dialed into. PPPsetAuthenticator() sets a name and password that will be required from the peer before a connection will be established. A common situation with dial-up PPP is that an ISP will want to authenticate the dialer before PPP negotiation. There are no real standards for doing this, so each ISP is potentially different. The best way to develop a correct sequence of ModemSend() and ModemExpect() commands is to connect to the ISP using a terminal program on a PC. You can then take note of the necessary sequence to start PPP negotiation. The above consideration is only useful if you are intending to use the application with only one ISP. If you want something more general, then you will either have to allow the end-users of your application to add their own send/expect sequences (moving the problem to your customers), or write sufficiently general code to handle all the idiosyncrasies of various ISPs (an almost impossible task). Thankfully, ISPs are starting to standardize their PPP login processes or at least implement PPP autodetection. Here is a hypothetical session as seen by a terminal program. Characters typed in and sent to the ISP or the modem are displayed in bold. AT OK ATDT5554545 OK CONNECT 28800 Welcome to someisp.com Login?rabbit Password:Ilikecarrots Logging in as rabbit Start PPP $*($}}}}}$}$#$#${@#>>}}FF}}$} From this session we could use ModemSend() and ModemExpect() to create a dial-up function like this:

Chapter 18: PPP Driver

533

int myDialUp(){ if(ModemOpen(57600) == 0){ return 0; } if(ModemInit() == 0){ return 0; } ModemSend(ATDT5554545\r); if (ModemExpect(OK, 2000) == 0)){ return 0; // something is wrong with the modem } if(ModemExpect(CONNECT, 30000) == 0){ return 0; //didnt connect to the ISP } if(ModemExpect(Login?, 5000) == 0){ return 0; } ModemSend(rabbit\r); if(ModemExpect(word:, 5000) == 0){ return 0; } ModemSend(Ilikecarrots\r); if(ModemExpect(PPP, 5000) == 0){ return 0; //probably a failed login } ModemClose(); sock_init(); PPPinit(57600); PPPflowcontrolOn(); return 1; //all done } As you can see, ModemExpect() will pick up any part of the received string. Clever use of this allows the initialization to be fairly generic, but subtle differences between ISPs will often require customized sequences such as this.

18.5.5 Link Teardown


Tearing down the link must also be done in stages. First, a terminate request must be sent to the peer. This is done with PPPshutdown(). PPPshutdown() will return once an acknowledgement has been sent by the peer, or after a time-out period. This is followed by a call to PPPclose(), which unloads the PPP serial driver. If the connection is via a modem, the modem must then be hung up. First the regular serial driver is reopened with ModemOpen(). ModemHangup() sends the hang up and reset commands to the modem. Finally, a call to ModemClose() shuts down the serial driver.

534

TCP/IP Users Manual

18.6 Configuring PPP (Dynamic C 7.30)


Since multiple interfaces are supported, your application should call ifconfig() to change PPP interface parameters at run-time, or define suitable IFCONFIG_PPP* macros for boot-time configuration of each PPP interface (both serial and PPPoE). You select serial port hardware to use with PPP by defining USE_PPP_SERIAL before including dcrtcp.lib. Similarly, you select PPPoE by defining USE_PPPOE.

18.6.1 Serial Port Selection


PPP over asynchronous serial requires a suitable Rabbit serial port to be selected. You can use any of the available ports, since they all support asynchronous communications. The serial port selection is entirely dynamic, however there is a fixed mapping between interface numbers and serial port hardware. IF_PPP0 always represents serial port A. IF_PPP1 is always serial port B, and so on. The serial port hardware to use is determined by the USE_PPP_SERIAL macro, which your application defines in order to specify PPP serial interfaces. USE_PPP_SERIAL is set to a bitwise OR combination of numbers representing the desired serial port(s). Ports are assigned according to the following table.
Table 8. Bitmap Values for USE_PPP_SERIAL Interface Number Serial Port Bitmap Value

IF_PPP0 IF_PPP1 IF_PPP2 IF_PPP3

SERA SERB SERC SERD

0x01 0x02 0x04 0x08

The Rabbit 3000 supports an additional two serial ports, SERE and SERF, however the TCP/IP library does not fully support use of these ports for PPP. If multiple PPP serial interfaces are required, use (for example) #define USE_PPP_SERIAL 0x0C which, as the bitwise combination of 0x04 and 0x08, specifies SERC (IF_PPP2) and SERD (IF_PPP3).

18.6.2 PPPoE Port Selection


Since all Z-World controller boards currently have at most a single Ethernet driver chip, only a single PPPoE interface is available (however it can be shared with non-PPPoE Ethernet over the same hardware - non-PPPoE Ethernet will use interface IF_ETH0 while PPPoE will use IF_PPPOE0).

Chapter 18: PPP Driver

535

18.6.3 ifconfig() Options for PPP


The ifconfig() parameter identifiers described in this section pertain to any PPP interface, whether serial or Ethernet. There are a considerable number of options (detailed in Section 18.6.4) pertinent to PPP over asynchronous serial. PPPoE does not, as yet, require any special configuration options because of its relative simplicity. The parameter identifiers listed here are passed to the ifconfig() function. They can also be used in the appropriate IFCONFIG_PPP* macro definitions, to ensure that the interface(s) are initialized correctly at boot time. For example, a run-time change to the userid and password might be coded as follows: ifconfig (IF_PPP2, IFS_PPP_REMOTEAUTH, myUserid, myPassword, IFS_END); The same definition, for boot-time initialization, might be coded as #define IFCONFIG_PPP2 \ other parameters \ IFS_PPP_REMOTEAUTH, myUserid, myPassword, \ other parameters The general PPP properties set during initialization are:
Table 9. Macros for PPP Initialization (Serial and Ethernet) Macro Name Macro Description Data Type(s) for Macro Parms

IFS_PPP_ACCEPTIP IFS_PPP_REMOTEIP IFS_PPP_ACCEPTDNS IFS_PPP_REMOTEDNS IFS_PPP_AUTHCALLBACK IFS_PPP_INIT IFS_PPP_REMOTEAUTH IFS_PPP_LOCALAUTH

Accept peer's idea of our local IP address. Try to set IP address of peer. Accept a DNS server IP address from peer. Set DNS server IP addresses for peer (primary and secondary). Called when a peer attempts to authenticate. Sets up PPP with default parameters. Sets username and password to give to peer.

bool longword bool longword, longword int (*)() none char *, char *

Required username and password for incoming char *, char * peer

All of these IFS_PPP_* macros (except the initialization and callback) have IFG_PPP_* versions that allow an application to look at the properties that have been set.

536

TCP/IP Users Manual

18.6.4 ifconfig() Options for Serial PPP


The ifconfig() parameter identifiers described in this section pertain to serial PPP interfaces only. (You can specify these options for PPPoE interfaces, but they will be quietly ignored.) They may also be used in the appropriate IFCONFIG_PPP* macro definitions for boot-time initialization.
Table 10. Macros for PPP Initialization (for Serial) Macro Name Macro Description Data Type(s) for Macro Parms

IFS_PPP_SPEED IFS_PPP_RTSPIN IFS_PPP_CTSPINf IFS_PPP_USEPORTD IFS_PPP_FLOWCONTROL IFS_PPP_HANGUP

Set serial PPP speed (bps) Define the RTS pin. Define the CTS pin.

longword int, char *, int int, int

Use parallel port D instead of parallel port C for bool serial ports A and B. Turn hardware flow control on or off An optional string to send to the modem after PPP shuts down. bool char *

IFS_PPP_MODEMESCAPE

When enabled, sends modem escape sequences before send/expect or hangup sequence is: bool <delay>+++<delay> This is recognized by almost all modems to force them into command mode. A formatted send and expect sequence for dialing and shell login. Specify whether to use modem dialout string. char * bool

IFS_PPP_SENDEXPECT IFS_PPP_USEMODEM

All of these IFS_PPP_* macros have IFG_PPP_* versions that allow an application to look at the properties that have been set. The parameter for the IFS_PPP_SENDEXPECT option is a string containing a send/expect script to run when the PPP connection comes up. It is a series of tokens separated by spaces, alternating between a string to transmit, and a string to expect back.

Chapter 18: PPP Driver

537

For example: SEscript = ATDT5551212 CONNECT ogin: Joe User word: secret PPP; The sequence is: 1. Send ATDT5551212 - dials up an ISP. 2. Wait for the word CONNECT. 3. An empty send string, means dont send anything and wait for the next expect string. 4. Wait for login: or Login: By leaving off the L either one will match. 5. Send Joe User Note that this token is contained in single quotes, because it contains a space within it. 6. Wait for password: or Password: 7. Send the password. 8. Wait for the sequence PPP This indicates a PPP session has started.

18.6.4.1 Additional Rules for Send/Expect Scripts A carriage return character (ASCII 13) is automatically sent after each send token An ampersand(&) at the start of an expect token indicates that the driver should wait indefinitely for that token to be received. This is useful when waiting to answer a call, e.g., To set the modem to answer and wait indefinitely for a connection ATS0=1 &CONNECT

As mentioned above, an empty token is immediately skipped. This allows for a chain of
expect tokens to be used.

The macro PSS_MODEM_CONNECT_WAIT determines the total time for the script. If this
is exceeded, a timeout failure will occur and the interface will fail to come up. Using the ampersand modifier resets this timeout. Note that the IFS_PPP_USEMODEM specifies that PPP assumes that it is talking to a modem. When the interface is being brought up, it will first run through the send/expect script. After the script completes, PPP will assume that it can launch straight into LCP. If this is not appropriate, do not use IFS_PPP_SENDEXPECT or IFS_PPP_USEMODEM. Instead, use the facilities of MODEM.LIB to perform an appropriate login to the ISP. Only when this is complete should you call ifup(). Use of MODEM.LIB entails some limitations:

Only one PPP serial interface can use MODEM.LIB. You need to configure MODEM.LIB to match the serial port you are using for PPP. Ensure that you specify an IFCONFIG_PPP* default such that the interface remains
down at boot-time. In other words, do not append IFS_UP to the IFCONFIG_PPP* definition.

538

TCP/IP Users Manual

18.6.5 Starting and Stopping PPP Interfaces


Starting with version 7.30, the details of establishing and tearing down PPP links are handled by sock_init() and tcp_tick(), as are all other TCP/IP functions. The old functions PPPinit(), PPPstart() and PPPshutdown() should not be called. To start a PPP interface ifup() is used, just as it is for non-PPPoE Ethernet interfaces. One difference that you should note is that the interface will not usually be up after ifup() returns. ifup() only sets the process in motion, which takes much longer for PPP than it does for nonPPPoE Ethernet. Your application should be aware of this, since you will not be able to open sockets on an interface that is not fully enabled. If necessary, you can poll the interface to wait for it to come up. While polling, you must call tcp_tick() regularly. This is because it is actually the processing driven from tcp_tick() that drives the whole PPP negotiation machinery. The correct way to poll an interface is given by the following code fragment. This code includes tests for the possibility that the interface may not be able to come up (e.g., because of a time-out). ifup(IF_PPP2); while (ifpending(IF_PPP2) == 1) tcp_tick(); if (!ifstatus(IF_PPP2)) printf(Failed!\n); A similar consideration applies for bringing the interface down: ifdown(IF_PPP2); while (ifpending(IF_PPP2) == 3) tcp_tick(); Note that there is no need to test for an interface failing to come down, however the tear-down process may take a short time. If you wait for the interface to come down before restarting it then there is a better chance that the link will come back up successfully, since the peer will have been notified properly.

NOTE: For PPP links with IFS_PPP_USEMODEM in effect, the process of bringing the interface up and down will include the modem dial-out and hang-up procedure. If you had USEMODEM in effect when connecting, but turned it off during the connection, then ifdown() will not perform modem hang-up. You will need to manually hang up the modem (or possibly just renegotiate from the LCP phase, if this is what you intended, by calling ifup()).

Chapter 18: PPP Driver

539

18.7 API Functions


This section describes the functions that compose the PPP driver and the functions for modem control.

18.7.1 Using Cofunctions


Establishing a PPP connection over a modem is time-consuming. Depending on the baud rate negotiated by the modem, the whole process can take 30 seconds or more. Much of this time is spent by the controller waiting for a response from the other end. In a practical application, where the controller has other tasks to perform, this may be unacceptable. For this, there are cofunction versions of all of the functions that wait for responses from the peer. There are still parts of the initialization process that create delays, but the effect is much smaller. Using cofunctions to establish a PPP connection has no advantage starting with Dynamic C 7.30, because none of the functions block.

CofModemExpect
int CofModemExpect( char *send_string, unsigned long timeout );
DESCRIPTION

Listens for a specific string to be sent by the modem. Yields to other tasks while waiting for input.
PARAMETERS

send_string timeout
RETURN VALUE

A NULL-terminated string to listen for. Maximum wait in milliseconds for a character.

1: The expected string was received. 0: A time-out occurred before receiving the string.
LIBRARY

MODEM.LIB

540

TCP/IP Users Manual

CofModemHangup
int CofModemHangup( void );
DESCRIPTION

Sends "ATH" and "ATZ" commands. Yields to other tasks while waiting for responses.
RETURN VALUE

1: Success. 0: Modem not responding.


LIBRARY

MODEM.LIB

CofModemInit
int CofModemInit( void );
DESCRIPTION

Resets modem with AT, ATZ commands. Yields to other tasks while waiting for responses.
RETURN VALUE

1: Success. 0: Modem not responding.


LIBRARY

MODEM.LIB

Chapter 18: PPP Driver

541

CofModemSend
void CofModemSend( char *send_string );
DESCRIPTION

Sends a string to the modem. Yields to other tasks while sending.


PARAMETERS

send_string
LIBRARY

A NULL-terminated string to be sent to the modem.

MODEM.LIB

CofPPPshutdown
int CofPPPshutdown( unsigned long timeout );
DESCRIPTION

Sends a Link Terminate Request packet. Waits for the link to be torn down. This function is deprecated starting with Dynamic C 7.30.
PARAMETERS

timeout

Number of milliseconds to wait before giving up on a response from the peer. Yields to other tasks while waiting.

RETURN VALUE

1:Shutdown succeeded. 0: Shutdown timed-out.


LIBRARY

PPP.LIB

542

TCP/IP Users Manual

CofPPPstart
int CofPPPstart( unsigned long timeout, int retry );
DESCRIPTION

Starts link negotiation process with a connected peer. It yields to other tasks. This function is deprecated starting with Dynamic C 7.30.
PARAMETERS

timeout

The number of milliseconds to wait between phases of negotiation before starting over. Number of times to retry the connection.

retry
RETURN VALUE

1: Negotiation succeeded. 0: A link could not be negotiated.


LIBRARY

PPP.LIB

ModemClose
void ModemClose( void );
DESCRIPTION

Closes the serial driver down.


LIBRARY

MODEM.LIB

Chapter 18: PPP Driver

543

ModemConnected
int ModemConnected( void );
DESCRIPTION

Returns true if the DCD line is asserted, meaning the modem is connected to a remote carrier.
RETURN VALUE

1: DCD line is active. 0: DCD inactive (nothing connected).


LIBRARY

MODEM.LIB

ModemExpect
int ModemExpect( char *send_string, unsigned long timeout );
DESCRIPTION

Listens for a specific string to be sent by the modem.


PARAMETERS

send_string timeout
RETURN VALUE

A NULL-terminated string to listen for. Maximum wait in milliseconds for a character.

1: The expected string was received. 0: A timeout occurred before receiving the string.
LIBRARY

MODEM.LIB

544

TCP/IP Users Manual

ModemHangup
int ModemHangup( void );
DESCRIPTION

Sends "ATH" and "ATZ" commands


RETURN VALUE

1: Success. 0: Modem not responding.


LIBRARY

MODEM.LIB

ModemInit
int ModemInit( void );
DESCRIPTION

Resets modem with AT, ATZ commands.


RETURN VALUE

1: Success. 0: Modem not responding.


LIBRARY

MODEM.LIB

Chapter 18: PPP Driver

545

ModemOpen
int ModemOpen( unsigned long baud );
DESCRIPTION

Starts up communication with an external modem.


PARAMETERS

baud
RETURN VALUE

The baud rate for communicating with the modem.

1: External modem detected 0: Not connected to external modem


LIBRARY

MODEM.LIB

ModemReady
int ModemReady( void );
DESCRIPTION

Returns true if the DSR line is asserted.


RETURN VALUE

1: DSR line is active. 0: DSR inactive (nothing connected).


LIBRARY

MODEM.LIB

546

TCP/IP Users Manual

ModemRinging
int ModemRinging( void );
DESCRIPTION

Returns true if the RI line is asserted, meaning that the line is ringing.
RETURN VALUE

1: RI line is active. 0: RI inactive (nothing connected).


LIBRARY

MODEM.LIB

ModemSend
void ModemSend( char *send_string );
DESCRIPTION

Sends a string to the modem.


PARAMETERS

send_string
LIBRARY

A NULL-terminated string to be sent to the modem.

MODEM.LIB

Chapter 18: PPP Driver

547

ModemStartPPP
void ModemStartPPP( void );
DESCRIPTION

Hands control of the serial line over to the PPP driver.


LIBRARY

MODEM.LIB

PPPactive
int PPPactive( void );
DESCRIPTION

Returns boolean value indicating if there is currently an active link to a peer.


RETURN VALUE

>0: Active link to peer. 0: No active link.


LIBRARY

PPP.LIB

PPPclose
void PPPclose( void );
DESCRIPTION

Closes the serial port and unloads the PPP interrupt service routine. This function is deprecated starting with Dynamic C 7.30.
LIBRARY

PPPLINK.LIB

548

TCP/IP Users Manual

PPPinit
void PPPinit( unsigned long baud );
DESCRIPTION

Initializes the PPP driver, sets parameters. Must be called immediately following a call to sock_init(). This function is deprecated starting with Dynamic C 7.30. Please see the function description for ifconfig() for more information about equivalent functionality.
PARAMETERS

baud
LIBRARY

The baud rate of the serial port PPP is running on (port C by default).

PPP.LIB

PPPflowcontrolOff
void PPPflowcontrolOff( void );
DESCRIPTION

Deactivates hardware flow control for the serial link. This function is deprecated starting with Dynamic C 7.30. The same functionality is obtained by calling the function ifconfig() with the IFS_PPP_FLOWCONTROL parameter set to zero.
LIBRARY

PPPLINK.LIB

Chapter 18: PPP Driver

549

PPPflowcontrolOn
void PPPflowcontrolOn( void );
DESCRIPTION

Activates hardware flow control for the serial link. The pins used for flow control are defined in PPPLINK.LIB as follows: PPP_CTSPORT: the port address for the CTS input line. PPP_CTSPIN: the pin number of the CTS input line. PPP_RTSPORT: the port address of the RTS output line. PPP_RTSSHADOW: the name of the ports shadow register. PPP_RTSPIN: the pin number of the RTS output line. This function is deprecated starting with Dynamic C 7.30. The same functionality is obtained by calling the function ifconfig() with the IFS_PPP_FLOWCONTROL parameter set to 1.
LIBRARY

PPPLINK.LIB

PPPstart
int PPPstart( unsigned long timeout, int retry );
DESCRIPTION

Starts link negotiation process with a connected peer. This function is deprecated starting with Dynamic C 7.30.
PARAMETERS

timeout

Number of milliseconds to wait between phases of negotiation before starting over. Number of times to retry the connection.

retry
RETURN VALUE

1: Negotiation succeeded. 0: A link could not be negotiated.


LIBRARY

PPP.LIB

550

TCP/IP Users Manual

PPPnegotiateIP
void PPPnegotiateIP( unsigned long local_ip, unsigned long remote_ip );
DESCRIPTION

Sets PPP driver to negotiate IP addresses for itself and the remote peer. Otherwise, the system will rely on the remote peer to set addresses.
PARAMETERS

local_ip remote_ip
LIBRARY

IP number to use for this PPP connection. IP number that the remote peer should be set to.

PPP.LIB

PPPnegotiateDNS
void PPPnegotiateDNS( unsigned long dns_ip );
DESCRIPTION

Sets PPP driver to configure a DNS address for the remote peer. This function is not available starting with Dynamic C 7.26. The same result may be obtained using the IFS_PPP_SETREMOTEDNS parameter when calling ifconfig(). Additional functionality was introduced with Dynamic C 7.30 in the ifconfig() function with the IFS_PPP_ACCEPTDNS parameter, which allows accepting the address of the DNS server from the peer.
PARAMETERS

dns_ip
LIBRARY

IP number for the DNS server.

PPP.LIB

Chapter 18: PPP Driver

551

PPPSerialGetErrors
word PPPSerialGetErrors( void );
DESCRIPTION

Gets a bit field with flags set for any errors that occurred. These flags are then cleared, so that a particular error will only cause the flag to be set once.
RETURN VALUE

A bit field with flags for various errors. The errors along with their bit masks are as follows:

PPP_NOBUFFER 0x01 PPP_RXOVERRUN 0x02 PPP_BUFFEROVERFLOW 0x08


The high byte of the return value contains the number of CRC errors since the last call to this function (0-255).
LIBRARY

PPPLINK.LIB

552

TCP/IP Users Manual

PPPsetAuthenticatee
void PPPsetAuthenticatee( char *username, char *password );
DESCRIPTION

Sets the driver up to send a PAP authentication message to a peer when requested.
PARAMETERS

username

The username to send to the peer. The argument string is not copied, so the argument string must stay constant. The password to send to the peer. The argument string is not copied, so the argument string must stay constant.

password

LIBRARY

PPP.LIB

PPPsetAuthenticator
void PPPsetAuthenticator( char *username, char *password );
DESCRIPTION

Sets the driver up to require a PAP authentication message from a peer. Negotiation will fail unless the peer sends the specified username/password pair. This function is generally used when the Rabbit is acting as a dial-in server.
PARAMETERS

username password
LIBRARY

The user name that the peer must match for the link to proceed. The password that the peer must match for the link to proceed.

PPP.LIB

Chapter 18: PPP Driver

553

PPPshutdown
int PPPshutdown( unsigned long timeout );
DESCRIPTION

Sends a Link Terminate Request packet. Waits for link to be torn down.
PARAMETERS

timeout

Number of milliseconds to wait before giving up on a response from the peer.

RETURN VALUE

1: Shutdown succeeded. 0: Shutdown timed-out.


LIBRARY

PPP.LIB

ResetPPP
void ResetPPP( void );
DESCRIPTION

Under normal operations, this function will not be needed; the modem control functions make it unnecessary. There are, however, conditions that may make it useful. This function is not available starting with Dynamic C 7.26. Starting with 7.30, the ifconfig() parameter IFS_PPP_INIT sets up PPP with default parameters.
LIBRARY

PPP.LIB

554

TCP/IP Users Manual

Notice to Users
Z-WORLD PRODUCTS ARE NOT AUTHORIZED FOR USE AS CRITICAL COMPONENTS IN LIFE-SUPPORT DEVICES OR SYSTEMS UNLESS A SPECIFIC WRITTEN AGREEMENT REGARDING SUCH INTENDED USE IS ENTERED INTO BETWEEN THE CUSTOMER AND Z-WORLD PRIOR TO USE. Life-support devices or systems are devices or systems intended for surgical implantation into the body or to sustain life, and whose failure to perform, when properly used in accordance with instructions for use provided in the labeling and users manual, can be reasonably expected to result in significant injury. No complex software or hardware system is perfect. Bugs are always present in a system of any size. In order to prevent danger to life or property, it is the responsibility of the system designer to incorporate redundant protective mechanisms appropriate to the risk involved. The TCP/IP software used in the Rabbit 2000 TCP/IP Development Kit is designed for use only with Rabbit Semiconductor chips.

Index
Symbols
#echo var .......................................................... 311 #exec cmd ........................................................ 311 #include file ..................................................... 311

C
callbacks .......................................................... 410 CGI ................................................................ 68 FTP data transfers ........................................ 348 interface status ....................................... 15, 106 IP address conflict .......................................... 70 PPP authentication ....................................... 104 sending HTTP headers ................................. 303 SNMP objects ...................................... 410, 456 TCP and UDP data handlers .......................... 49 CGI .......................................................... 298, 312 checksums ........................................................ 165 clock value ....................................................... 303 communication channel ..................................... 57 console, serial-based ................................ 491525

Numerics
2MSL ............................................................... 203 3-way handshake ............................................... 37

A
anonymous login .............................................. 353 application protocols FTP client ..................................................... 343 FTP server .................................................... 353 HTTP ........................................................... 295 POP3 client .................................................. 395 SMTP client ................................................. 387 telnet ............................................................. 479 TFTP client .................................................. 379 ARP_CONFLICT_CALLBACK ...................... 70 ARP_LONG_EXPIRY ...................................... 69 ARP_NO_ANNOUNCE ................................... 70 ARP_PERSISTENCE ....................................... 70 ARP_PURGE_TIME ......................................... 69 ARP_ROUTER_TABLE_SIZE .................. 24, 70 ARP_SHORT_EXPIRY .................................... 69 ARP_TABLE_SIZE .................................... 24, 70 authentication ................................................... 297

D
daemons FTP client ..................................................... 345 FTP server .................................................... 373 HTTP server ................................................. 332 POP3 client .................................................. 399 tcp_tick ........................................................ 204 telnet ............................................................ 487 tftp_tick ........................................................ 383 Zconsole ....................................................... 507 data handler callbacks ........................................ 49 DCRTCP_DEBUG ............................................ 29 DCRTCP_VERBOSE ....................................... 30 DHCP/BOOTP, See BOOTP/DHCP DHCP_CHECK ................................................. 19 DHCP_CLASS_ID ............................................ 19 DHCP_CLIENT_ID .......................................... 20 DHCP_CLIENT_ID_LEN ................................ 20 DHCP_CLIENT_ID_MAC ............................... 20 DHCP_USE_BOOTP ........................................ 19 DHCP_USE_TFTP ............................................ 19 DISABLE_DNS .......................................... 18, 71 DISABLE_TCP ................................................. 18 DNS ................................................................... 71 DNS_MAX_DATAGRAM_SIZE .............. 25, 71 DNS_MAX_NAME .................................... 25, 71 DNS_MAX_RESOLVES ............................ 25, 71 DNS_MIN_KEEP_COMPLETED ............. 29, 72 DNS_NUMBER_RETRIES ........................ 29, 72 DNS_RETRY_TIMEOUT .......................... 29, 71 DNS_SOCK_BUF_SIZE ............................ 25, 72 drivers link layer .......................................................... 6 dynamic web pages .......................................... 308

B
bandwidth .................................................... 57, 73 basic authentication ......................................... 297 BOOTP/DHCP _bootpdata ...................................................... 22 _bootpdone ..................................................... 21 _bootperror ..................................................... 22 _bootphost ...................................................... 21 _bootpon ........................................................ 20 _bootpsize ...................................................... 21 _bootptimeout ................................................ 21 _dhcphost ....................................................... 20 _dhcplife ........................................................ 21 _dhcpt1 ........................................................... 21 _dhcpt2 ........................................................... 21 _smtpsrv ......................................................... 22 _survivebootp ................................................. 20 used with TFTP ............................................ 379 broadcast packets ... 33, 41, 43, 207, 209, 211, 214 buffer sizes ......................................................... 36

TCP/IP Users Manual

557

E
e-mail POP3 client ...........................................395401 SMTP client .......................................... 387393 ephemeral connection ........................................ 34 error messages .................................................. 167 ETH_MAXBUFS ............................................... 24 ETH_MTU ......................................................... 24 Ethernet ports .................................................................. 3 Ethernet Transmission Unit ............................. 157

F
file extensions .......................................... 297, 307 file handlers ...................................................... 356 file size ............................................................. 346 file transfer ....................................................... 344 firewall ............................................................. 375 flow control .............................. 515, 529, 549, 550 FTP client .................................................343351 FTP server ................................................ 353377 FTP server commands .............................. 375376 Function Reference Addressing _arp_resolve ............................................... 85 arpcache_create ..........................................77 arpcache_flush ............................................ 78 arpcache_hwa ............................................. 79 arpcache_ipaddr ..........................................81 arpcache_load ............................................. 82 arpcache_search ..........................................84 arpresolve_check ........................................ 86 arpresolve_ipaddr ....................................... 87 arpresolve_start ..........................................88 dhcp_acquire .............................................. 91 dhcp_get_timezone ..................................... 92 dhcp_release ............................................... 93 getdomainname ..........................................94 gethostid .....................................................95 gethostname ................................................96 getpeername ................................................97 getsockname ............................................... 98 psocket ...................................................... 129 resolve ...................................................... 130 resolve_cancel .......................................... 131 resolve_name_check ................................ 132 resolve_name_start ................................... 133 router_add ................................................. 135 router_del_all ............................................ 135 router_delete ............................................. 136 router_for .................................................. 137 router_print ............................................... 138 router_printall ........................................... 139

setdomainname ......................................... 141 sethostid .................................................... 142 sethostname .............................................. 143 udp_bypass_arp ........................................ 205 CGI cgi_redirectto ............................................ 326 cgi_sendstring ........................................... 327 Configuration ifconfig ..................................................... 101 tcp_config ................................................. 195 Console con_backup ............................................... 508 con_backup_bytes .................................... 508 con_backup_reserve ................................. 509 con_chk_timeout ...................................... 509 con_load_backup ...................................... 510 con_reset_io .............................................. 510 con_set_backup_lx ................................... 511 con_set_files_lx ........................................ 511 con_set_timeout ........................................ 512 con_set_user_idle ..................................... 512 con_set_user_timeout ............................... 513 console_init .............................................. 507 console_tick .............................................. 507 Cookie http_setcookie ........................................... 337 Data Conversion aton ............................................................. 89 htonl ............................................................ 99 htons ......................................................... 100 http_contentencode ................................... 329 http_date_str ............................................. 330 http_urldecode .......................................... 338 inet_addr ................................................... 112 inet_ntoa ................................................... 113 ntohl .......................................................... 121 ntohs ......................................................... 122 paddr ......................................................... 123 rip .............................................................. 134 E-mail pop3_getmail ............................................ 398 pop3_init ................................................... 397 pop3_tick .................................................. 399 smtp_mailtick ........................................... 391 smtp_sendmail .......................................... 389 smtp_sendmailxmem ................................ 390 smtp_status ............................................... 392 Ethernet pd_getaddress ........................................... 124 pd_havelink .............................................. 125 pd_powerdown ......................................... 126 pd_powerup .............................................. 127 FTP Client ftp_client_filesize ..................................... 346

558

TCP/IP Users Manual

ftp_client_setup ........................................ 344 ftp_client_tick .......................................... 345 ftp_client_xfer .......................................... 347 ftp_data_handler ....................................... 348 ftp_last_code ............................................ 350 FTP Server ftp_init ...................................................... 368 ftp_set_anonymous .................................. 371 ftp_shutdown ............................................ 372 ftp_tick ..................................................... 373 HTML Forms http_finderrbuf ......................................... 331 http_nextfverr ........................................... 333 http_parseform ......................................... 334 http_scanpost ............................................ 335 sspec_addfv .............................................. 235 sspec_findfv ............................................. 243 sspec_getformtitle .................................... 249 sspec_getfvdesc ........................................ 251 sspec_getfventrytype ................................ 252 sspec_getfvlen .......................................... 253 sspec_getfvname ...................................... 254 sspec_getfvnum ........................................ 255 sspec_getfvopt .......................................... 256 sspec_getfvoptlistlen ................................ 257 sspec_getfvreadonly ................................. 258 sspec_getpreformfunction ........................ 262 sspec_setformepilog ................................. 278 sspec_setformfunction ............................. 279 sspec_setformprolog ................................ 280 sspec_setformtitle ..................................... 281 sspec_setfvcheck ...................................... 282 sspec_setfvdesc ........................................ 283 sspec_setfventrytype ................................ 284 sspec_setfvfloatrange ............................... 285 sspec_setfvlen .......................................... 286 sspec_setfvname ....................................... 287 sspec_setfvoptlist ..................................... 288 sspec_setfvrange ...................................... 289 sspec_setfvreadonly ................................. 290 sspec_setpreformfunction ........................ 291 HTTP Server http_findname .......................................... 331 http_handler ............................................. 332 http_idle ................................................... 332 http_init .................................................... 333 http_setauthentication .............................. 336 Initialization sock_tick .................................................. 186 Interface ifdown ...................................................... 108 ifpending .................................................. 109 ifstatus ...................................................... 110 ifup ........................................................... 111

ip_iface ..................................................... 114 ip_print_ifs ............................................... 115 is_valid_iface ........................................... 118 sock_iface ................................................ 162 Modem CofModemExpect .................................... 540 CofModemHangup .................................. 541 CofModemInit .......................................... 541 CofModemSend ....................................... 542 ModemClose ............................................ 543 ModemConnected .................................... 544 ModemExpect .......................................... 544 ModemHangup ........................................ 545 ModemInit ................................................ 545 ModemOpen ............................................ 546 ModemReady ........................................... 546 ModemRinging ........................................ 547 ModemSend ............................................. 547 Multicast multicast_joingroup ................................. 119 multicast_leavegroup ............................... 120 Ping _chk_ping ................................................... 90 _ping ........................................................ 128 _send_ping ............................................... 140 PPP CofPPPshutdown ..................................... 542 CofPPPstart .............................................. 543 ModemStartPPP ....................................... 548 PPPactive ................................................. 548 PPPclose ................................................... 548 PPPflowcontrolOff ................................... 549 PPPflowcontrolOn ................................... 550 PPPinit ...................................................... 549 PPPnegotiateDNS .................................... 551 PPPnegotiateIP ......................................... 551 PPPSerialGetErrors .................................. 552 PPPsetAuthenticatee ................................ 553 PPPsetAuthenticator ................................ 553 PPPshutdown ........................................... 554 PPPstart .................................................... 550 ResetPPP .................................................. 554 Socket Configuration sock_mode ............................................... 164 sock_set_tos ............................................. 180 sock_set_ttl .............................................. 181 tcp_clearreserve ....................................... 194 tcp_reserveport ......................................... 203 Socket Connection _abort_socks .............................................. 76 sock_abort ................................................ 144 sock_close ................................................ 151 sock_established ...................................... 155 tcp_keepalive ........................................... 198

TCP/IP Users Manual

559

Socket I/O Buffer sock_rbleft ................................................ 171 sock_rbsize ............................................... 172 sock_rbused .............................................. 173 sock_tbleft ................................................ 183 sock_tbsize ............................................... 184 sock_tbused .............................................. 185 Socket Status ip_timer_expired ...................................... 116 ip_timer_init ............................................. 117 sock_alive ................................................. 145 sock_bytesready ....................................... 150 sock_dataready ......................................... 152 sock_error ................................................. 154 sock_perror ............................................... 167 sock_resolved ........................................... 179 sockerr ...................................................... 153 sockstate ................................................... 182 tcp_tick ..................................................... 204 TCP Socket I/O sock_aread ................................................ 146 sock_awrite ............................................... 147 sock_axread .............................................. 148 sock_axwrite ............................................. 149 sock_fastread ............................................ 156 sock_fastwrite ........................................... 157 sock_flush ................................................. 158 sock_flushnext .......................................... 159 sock_getc .................................................. 160 sock_gets .................................................. 161 sock_preread ............................................. 168 sock_putc .................................................. 169 sock_puts .................................................. 170 sock_read .................................................. 174 sock_write ................................................ 190 sock_xfastread .......................................... 191 sock_xfastwrite ......................................... 192 sock_yield ................................................. 193 tcp_extlisten .............................................. 196 tcp_extopen .............................................. 197 tcp_listen .................................................. 199 tcp_open ................................................... 201 TCP/IP servers object list http_addfile ............................................... 328 http_delfile ................................................ 330 shtml_addfunction .................................... 339 shtml_addvariable .................................... 340 shtml_delfunction ..................................... 341 shtml_delvariable ..................................... 341 sspec_addform .......................................... 232 sspec_addfsfile ......................................... 233 sspec_addfunction .................................... 234 sspec_addrootfile ...................................... 236 sspec_adduser ........................................... 237

sspec_addvariable ..................................... 238 sspec_addxmemfile .................................. 239 sspec_addxmemvar .................................. 240 sspec_aliasspec ......................................... 241 sspec_checkaccess .................................... 242 sspec_findfsname ..................................... 245 sspec_findname ........................................ 244 sspec_findnextfile ..................................... 246 sspec_getfileloc ........................................ 247 sspec_getfiletype ...................................... 248 sspec_getfunction ..................................... 250 sspec_getfvspec ........................................ 259 sspec_getlength ........................................ 260 sspec_getname .......................................... 261 sspec_getrealm ......................................... 263 sspec_gettype ............................................ 264 sspec_getuserid ......................................... 265 sspec_getusername ................................... 266 sspec_getvaraddr ...................................... 267 sspec_getvarkind ...................................... 268 sspec_getvartype ...................................... 269 sspec_needsauthentication ........................ 270 sspec_readfile ........................................... 271 sspec_readvariable .................................... 272 sspec_remove ........................................... 273 sspec_removeuser ..................................... 274 sspec_resizerootfile .................................. 275 sspec_restore ............................................ 276 sspec_save ................................................ 277 sspec_setrealm .......................................... 292 sspec_setsavedata ..................................... 293 sspec_setuser ............................................ 294 TCP/IP Stack sock_init ................................................... 163 tcp_tick ..................................................... 204 TCP/IP users list sauth_adduser ........................................... 222 sauth_authenticate .................................... 223 sauth_getpassword .................................... 224 sauth_getuserid ......................................... 225 sauth_getusername ................................... 226 sauth_getwriteaccess ................................ 227 sauth_removeuser ..................................... 228 sauth_setpassword .................................... 229 sauth_setwriteaccess ................................. 231 Telnet telnet_close ............................................... 487 telnet_init .................................................. 486 telnet_tick ................................................. 487 vserial_close ............................................. 480 vserial_init ................................................ 481 vserial_keepalive ...................................... 482 vserial_listen ............................................. 483 vserial_open .............................................. 484

560

TCP/IP Users Manual

vserial_tick ............................................... 485 TFTP Client tftp_exec ................................................... 385 tftp_init ..................................................... 381 tftp_initx ................................................... 382 tftp_tick .................................................... 383 tftp_tickx .................................................. 384 UDP Socket I/O udp_close ................................................. 206 udp_extopen ............................................. 207 udp_open .................................................. 209 udp_peek .................................................. 211 udp_recv ................................................... 212 udp_recvfrom ........................................... 213 udp_send .................................................. 214 udp_sendto ............................................... 215 udp_waitopen ........................................... 216 udp_waitsend ........................................... 217 udp_xsendto ............................................. 218 UDP Socket I/O (pre-DC 7.05) sock_fastread ............................................ 156 sock_fastwrite .......................................... 157 sock_read ................................................. 174 sock_recv ................................................. 175 sock_recv_from ........................................ 177 sock_recv_init .......................................... 178 sock_write ................................................ 190 udp_close ................................................. 206 udp_open .................................................. 209

directed ping .................................................. 13 dynamic configuration ................................... 11 last-used DHCP server ................................... 20 last-usedBOOTP/TFTP server ....................... 21 lease ......................................................... 11, 21 mail server ...................................................... 22 origin of received datagram ........................... 44 runtime configuration .................................... 12 setting to zero ................................................. 36 sources of ......................................................... 9 Zconsole configuration .................................. 14 ISPs and MAC addresses ................................... 14

K
KEEPALIVE_NUMRETRYS ........................... 28 KEEPALIVE_WAITTIME ............................... 28

L
latency .......................................................... 58, 68 link layer drivers .................................................. 6

M
MAC address ............................................... 14, 65 macros ARP ................................................................ 69 BOOTP/DHCP .............................................. 19 buffer/resource sizing .................................... 22 DNS ............................................................... 71 FTP server .................................................... 354 HTTP server ................................................. 301 including additional functionality .................. 18 interface configuration ..................................... 4 interface configuration (7.30 and later) ......... 26 interface selection ............................................ 5 link layer driver ................................................ 7 miscellaneous ................................................. 30 network configuration (pre 7.30) ................... 25 program debugging ........................................ 29 removing unwanted functionality .................. 18 serial ports for telnet .................................... 479 SNMP client ................................................. 388 telnet (7.05 and later) ................................... 480 telnet (pre 7.05) ............................................ 486 timers and counters ........................................ 28 TOS and TTL ................................................. 31 Zconsole ....................................................... 518 managed objects .............................................. 404 MAX_COOKIES ............................................... 24 MAX_DOMAIN_LENGTH ............................. 25 MAX_NAMESERVERS ................................... 24 MAX_RESERVEPORTS .................................. 25 MAX_SOCKET_LOCKS ........................... 22, 53 MAX_SOCKETS .............................................. 22

H
host group .......................................................... 73 HTML forms .................................... 221, 312325 HTTP configuration macros ............................ 301 HTTP server ............................................. 295341 HttpRealm ........................................................ 297 HttpSpec .......................................................... 296 HttpState .......................................................... 298 HttpType .......................................................... 297

I
ICMP_TOS ........................................................ 31 IF_* ...................................................................... 4 IFCONFIG_* ..................................................... 27 IGMP ................................................................. 73 interfaces configuration .............................................. 814 enable/disable support ...................................... 5 single ................................................................ 7 sum of physical ................................................ 6 supported types ................................................ 3 IP addresses broadcast packets ..................................... 41, 43 default ........................................................ 9, 26

TCP/IP Users Manual

561

MAX_STRING .................................................. 24 MAX_TCP_SOCKET_BUFFERS ............ 22, 197 MAX_UDP_SOCKET_BUFFERS ................... 23 memmap ............................................................. 45 MIB .................................................................. 405 MIME types ............................................. 297, 307 modem interface ............................................... 528 MSS (maximum segment size) .......................... 23 MTU ................................................................. 157 multicasting ................................................ 73, 207 multitasking ........................................................ 53 MY_DOMAIN ............................................. 23, 25 MY_GATEWAY ............................................... 25 MY_IP_ADDRESS ........................................... 26 MY_NAMESERVER ........................................ 26 MY_NETMASK ................................................26

RETRAN_STRAT_TIME ........................... 28, 62 RLER encoding ................................................ 467 router ...................................................... 69, 70, 73 RTT .................................................................... 58

S
sample programs FTP server .................................................... 374 POP3 client ................................................... 400 SMTP client ................................................. 393 SNMP ........................................................... 408 telnet client ................................................... 489 telnet server .................................................. 488 Zconsole ....................................................... 521 SAUTH_MAXNAME ..................................... 221 SAUTH_MAXUSERS ..................................... 221 SERIAL_PORT_SPEED ................................. 486 server utilities .................................................. 219294 server spec list .................................................. 219 SMI ........................................................... 404, 406 SMTP client ............................................. 387393 SMTP_DEBUG ............................................... 388 SMTP_DOMAIN ............................................. 388 SMTP_SERVER .............................................. 388 SMTP_TIMEOUT ........................................... 388 SNMP ....................................................... 403478 agent ............................................................. 404 callback function .......................................... 410 RLER encoding ............................................ 467 SOCK_BUF_SIZE ............................................. 23 socket abort all ........................................................... 76 buffers ............................................................ 35 data structure .................................................. 34 default mode ................................................... 40 definition ........................................................ 34 empty line vs empty buffer .......................... 150 locks ....................................................... 53, 164 SSI ............................................................ 301, 311 SSPEC_MAXNAME ....................................... 221 SSPEC_MAXSPEC ......................................... 221 SSPEC_USERSPERRESOURCE ................... 221 SSPEC_XMEMVARLEN ............................... 221 stack configuration ................................................ 38 free space for TFTP functions ...................... 380 initialization ...................................................... 7 static web pages ............................................... 306

N
Nagle algorithm .......................................... 60, 164 NET_ADD_ENTROPY ..................................... 30 NET_COARSELOCK ....................................... 30 network addressing ............................................ 69 network management ....................................... 403

O
optimizations ...................................................... 57

P
packet ............................................................... 403 acknowledgement ..................................... 58, 60 processing ....................................................... 46 size .................................................................. 59 TOS ................................................................ 65 passive open ..................................................... 353 password protection ......... 104, 219, 222, 229, 297 PDU (protocol data unit) .................................. 403 performance optimizing ..................................... 57 PKTDRV .............................................................. 7 POP_BUFFER_SIZE ....................................... 395 POP_DEBUG ................................................... 395 POP_NODELETE ........................................... 395 POP_PARSE_EXTRA ..................................... 395 POP3 client configuration ................................................ 395 port numbers ...................................................... 34 POST command ............................................... 315 PPP driver ................................................ 527554 PPP_MTU .......................................................... 24 PPP_PEERROUTE .......................................... 531

R
realm ................................................................. 297 reset clock ........................................................ 303

T
TCP socket ......................................................... 33 active open ..................................................... 37 control functions ............................................. 38

562

TCP/IP Users Manual

I/O functions .................................................. 40 blocking ...................................................... 49 non-blocking .............................................. 48 listen queue .................................................... 38 passive open ................................................... 36 TCP/IP initialization ................................................... 46 skeleton program ............................................ 45 TCP_BUF_SIZE ................................................ 23 TCP_CONNTIMEOUT ..................................... 28 TCP_FASTSOCKETS ...................................... 30 TCP_LAZYUPD ......................................... 29, 64 tcp_MaxBufSize ................................................ 23 TCP_MAXPENDING ....................................... 24 TCP_MAXRTO ................................................. 28 TCP_MINRTO ............................................ 29, 62 TCP_NO_CLOSE_ON_LAST_READ ............. 30 TCP_OPENTIMEOUT ...................................... 28 TCP_STATS ...................................................... 29 TCP_SYNQTIMEOUT ..................................... 28 TCP_TOS .......................................................... 31 TCP_TTL ........................................................... 31 TCP_TWTIMEOUT .................................... 28, 63 TCPCONFIG ................................................. 9, 26 telnet ........................................................ 479489 TELNET_COOKED ........................................ 486 TFTP client .............................................. 379385 throughput .................................................... 57, 68 tick rates ............................................................. 46 TIMEZONE ..................................................... 303

UDP_BUF_SIZE ............................................... 23 UDP_TOS .......................................................... 31 UDP_TTL .......................................................... 31 URL-encoded data ................................... 315, 316 USE_DHCP ................................................. 18, 19 USE_ETHERNET ......................................... 5, 26 USE_PPOE .......................................................... 5 USE_PPP_SERIAL ....................................... 5, 26 USE_PPPOE ...................................................... 26 USE_RESERVEDPORTS ................................. 38 USE_SNMP ....................................................... 18 users list ........................................................... 219 utilities for servers ................................... 219294

V
variable binding ............................................... 403 VSERIAL_DEBUG ......................................... 480 VSERIAL_NUM_GATEWAYS ..................... 480

W
well-known ports FTP server .................................................... 353 HTTP server ................................................. 302 POP3 ............................................................ 395 SMTP server ................................................ 387 SNMP agent ................................................. 404

Z
Zconsole ................................................... 491525 backup system .............................................. 516 circular buffers ............................................. 506 commands .................................................... 492 custom commands ....................................... 500 error messages .............................................. 501 I/O interfaces ................................................ 504 macros .................................................. 518520 physical connection ...................................... 506 terminal emulator ......................................... 515 using TCP/IP ................................................ 506

U
UDP broadcast packets ........................................... 41 performance ................................................... 41 UDP socket checksum ....................................................... 41 functions ......................................................... 41 open and close ................................................ 43 read ................................................................. 44 write ............................................................... 43

TCP/IP Users Manual

563

564

TCP/IP Users Manual

Dynamic C TCP/IP Functions


Listed Alphabetically

Symbols
_abort_socks ...................................76 _chk_ping .......................................90 _ping ............................................128 _send_ping ....................................140

ip_timer_init .................................117 is_valid_iface ................................118

M
multicast_joingroup .......................119 multicast_leavegroup .....................120

A
arp_resolve .....................................85 arpcache_create ...............................77 arpcache_flush ................................78 arpcache_hwa ..................................79 arpcache_iface .................................80 arpcache_ipaddr ..............................81 arpcache_load .................................82 arpcache_search ..............................84 arpresolve_check .............................86 arpresolve_ipaddr ............................87 arpresolve_start ...............................88 aton ................................................89

N
ntohl .............................................121 ntohs ............................................122

P
paddr ............................................123 pd_getaddress ...............................124 pd_havelink ..................................125 pd_powerdown ..............................126 pd_powerup ..................................127 psocket .........................................129

R
resolve ..........................................130 resolve_cancel ...............................131 resolve_name_check ......................132 resolve_name_start ........................133 rip ................................................134 router_add .....................................135 router_del_all ................................135 router_delete .................................136 router_for ......................................137 router_print ...................................138 router_printall ...............................139

D
dhcp_acquire ...................................91 dhcp_get_timezone ..........................92 dhcp_release ...................................93

G
getdomainname ...............................94 gethostid .........................................95 gethostname ....................................96 getpeername ....................................97 getsockname ...................................98

S
setdomainname .............................141 sethostid .......................................142 sethostname ..................................143 sock_abort ....................................144 sock_alive .....................................145 sock_aread ....................................146 sock_awrite ...................................147 sock_axread ..................................148 sock_axwrite .................................149 sock_bytesready ............................150 sock_close ....................................151 sock_dataready ..............................152 sock_error .....................................154 sock_established ............................155
Dynamic C TCP/IP Users Manual

H
htonl ...............................................99 htons .............................................100

I
ifconfig .........................................101 ifdown ..........................................108 ifpending ......................................109 ifstatus ..........................................110 ifup ...............................................111 inet_addr .......................................112 inet_ntoa .......................................113 ip_iface .........................................114 ip_print_ifs ...................................115 ip_timer_expired ...........................116

sock_fastread ................................156 sock_fastwrite ...............................157 sock_flush .....................................158 sock_flushnext ..............................159 sock_getc ......................................160 sock_gets ......................................161 sock_iface .....................................162 sock_init .......................................163 sock_mode ....................................164 sock_noflush .................................166 sock_perror ...................................167 sock_preread .................................168 sock_putc ......................................169 sock_puts ......................................170 sock_rbleft ....................................171 sock_rbsize ...................................172 sock_rbused ..................................173 sock_read ......................................174 sock_recv ......................................175 sock_recv_from .............................177 sock_recv_init ...............................178 sock_resolved ................................179 sock_set_tos ..................................180 sock_set_ttl ...................................181 sock_tbleft ....................................183 sock_tbsize ...................................184 sock_tbused ..................................185 sock_tick ......................................186 sock_wait_closed ..........................187 sock_wait_established ....................188 sock_wait_input ............................189 sock_write ....................................190 sock_xfastread ...............................191 sock_xfastwrite .............................192 sock_yield .....................................193 sockerr ..........................................153 sockstate .......................................182

U
udp_bypass_arp .............................205 udp_close ......................................206 udp_extopen ..................................207 udp_open ......................................209 udp_peek ......................................211 udp_recv .......................................212 udp_recvfrom ................................213 udp_send ......................................214 udp_sendto ....................................215 udp_waitopen ................................216 udp_waitsend ................................217 udp_xsendto ..................................218

T
tcp_clearreserve ............................194 tcp_config .....................................195 tcp_extlisten ..................................196 tcp_extopen ...................................197 tcp_keepalive ................................198 tcp_listen ......................................199 tcp_open .......................................201 tcp_reserveport ..............................203 tcp_tick .........................................204
Dynamic C TCP/IP Users Manual

Dynamic C TCP/IP Functions


Listed by Category

Addressing
_arp_resolve ....................................85 arpcache_create ...............................77 arpcache_flush ................................78 arpcache_hwa ..................................79 arpcache_iface .................................80 arpcache_ipaddr ..............................81 arpcache_load .................................82 arpcache_search ..............................84 arpresolve_check .............................86 arpresolve_ipaddr ............................87 arpresolve_start ...............................88 dhcp_acquire ...................................91 dhcp_get_timezone ..........................92 dhcp_release ...................................93 getdomainname ...............................94 gethostid .........................................95 gethostname ....................................96 getpeername ....................................97 getsockname ...................................98 psocket .........................................129 resolve ..........................................130 resolve_cancel ...............................131 resolve_name_check ......................132 resolve_name_start ........................133 router_add .....................................135 router_del_all ................................135 router_delete .................................136 router_for ......................................137 router_print ...................................138 router_printall ...............................139 setdomainname .............................141 sethostid .......................................142 sethostname ..................................143

udp_bypass_arp .............................205

Configuration ifconfig .........................................101 tcp_config .....................................195 Data Conversion aton ................................................89 htonl ...............................................99 htons ............................................100 inet_addr .......................................112 inet_ntoa .......................................113 ntohl .............................................121 ntohs ............................................122 paddr ............................................123 rip ................................................134 Ethernet
pd_getaddress ...............................124 pd_havelink ..................................125 pd_powerdown ..............................126 pd_powerup ..................................127

Initialization sock_init .......................................163 sock_tick ......................................186 Interface


ifdown ..........................................108 ifpending ......................................109 ifstatus ..........................................110 ifup ...............................................111 ip_iface .........................................114 ip_print_ifs ...................................115 is_valid_iface ................................118 sock_iface .....................................162

Dynamic C TCP/IP Users Manual

Multicast
multicast_joingroup .......................119 multicast_leavegroup .....................120

sockerr ..........................................153 sockstate .......................................182 tcp_tick .........................................204

Ping
_chk_ping .......................................90 _ping ............................................128 _send_ping ....................................140

Socket Configuration sock_mode ....................................164 sock_set_tos ..................................180 sock_set_ttl ...................................181 tcp_clearreserve ............................194 tcp_reserveport ..............................203 Socket Connection _abort_socks ...................................76 sock_abort ....................................144 sock_close ....................................151 sock_established ............................155 tcp_keepalive ................................198 Socket I/O Buffer sock_rbleft ....................................171 sock_rbsize ...................................172 sock_rbused ..................................173 sock_tbleft ....................................183 sock_tbsize ...................................184 sock_tbused ..................................185 Socket Status
ip_timer_expired ...........................116 ip_timer_init .................................117 sock_alive .....................................145 sock_bytesready ............................150 sock_dataready ..............................152 sock_error .....................................154 sock_perror ...................................167 sock_resolved ................................179

TCP Socket I/O sock_aread ....................................146 sock_awrite ...................................147 sock_axread ..................................148 sock_axwrite .................................149 sock_fastread ................................156 sock_fastwrite ...............................157 sock_flush .....................................158 sock_flushnext ..............................159 sock_getc ......................................160 sock_gets ......................................161 sock_preread .................................168 sock_putc ......................................169 sock_puts ......................................170 sock_read ......................................174 sock_write ....................................190 sock_xfastread ..............................191 sock_xfastwrite .............................192 sock_yield .....................................193 tcp_extlisten ..................................196 tcp_extopen ...................................197 tcp_listen ......................................199 tcp_open .......................................201 UDP Socket I/O udp_close ......................................206 udp_extopen ..................................207 udp_open ......................................209 udp_peek ......................................211 udp_recv .......................................212 udp_recvfrom ................................213 udp_send ......................................214 udp_sendto ....................................215 udp_waitopen ................................216 udp_waitsend ................................217
Dynamic C TCP/IP Users Manual

udp_xsendto ..................................218

UDP Socket I/O (pre-DC 7.05) sock_recv ......................................175 sock_recv_from .............................177 sock_recv_init ...............................178

Dynamic C TCP/IP Users Manual

Dynamic C TCP/IP Users Manual

S-ar putea să vă placă și