Skip to content

Grandstream unofficial TFTP provisioning server.

Notifications You must be signed in to change notification settings

sorend/gstftpd-server

Repository files navigation

Gratissip TFTPD Server

This project is an unofficial TFTP server for provisioning Grandstream VoIP phones. The project has been used in the free VoIP platform Gratissip, hence the name.

It consists of three parts:

  1. The TFTP provisioning server.
  2. An interface for integrating with existing infrastructure.
  3. A sample interface implementation using most JDBC databases.

Features

Basically it is a TFTP server, however with a few extensions for the Grandstream VoIP-phones.

  • Normal TFTP files serving from a tftproot, this means you can use it as any other normal TFTP server.
  • Serving Grandstream firmwares depending on user-choices, this means you can provision Grandstream phones with a specific firmware version automatically.
  • Serving Grandstream provisional configurations, this mean you can provision Grandstream phones with settings automatically.
  • Serving TFTP files hosted on a web-server (act as tftp-to-http proxy), this means you can serve files generated by a webserver over the TFTP protocol.

Grandstream is a company which sells inexpencive VoIP-phones. This is a seperate project which they may or may not be aware of. They are selling their own provosional server as a seperate product. If you want to use a provisional server professionally for your business, you should consider to buy it from them. Check their website {{http://www.grandstream.com/}}.

Where does Gratissip Tftpd come from?

It is based on the fwtftpd work of Martin Kihlgren, which is GPL - and hence this is also GPL. Read more about what that means in the GplLicense. You can find Martin's work here: {{http://troja.ath.cx/~zond/fwtftpd/}}.

Installation

The project can be built using Gradle, which is already included. After downloading, run the following command:

./gradlew distZip

This produces an installation file in the folder tftpd-server/build/distribution/tftpd-server.zip. You can unpack this file in a location of your choice. After this, you have to configure the server.

Defining which IP and port to listen on

In the configuration file you can define which IP and port the TFTPD server should listen on. Normally you should leave the port to 69, the standard tftp service port, however, in special cases you can here configure it to something else. Also you can define which IP to bind on. The default 0.0.0.0 IP means to bind on all IPs available on the machine.

<bean id="tftpdServer" class="net.tanesha.tftpd.core.Server">
	<property name="port" value="69" />
	<property name="bindhost" value="0.0.0.0" />
	<property name="vfs" ref="vfs" />
</bean>

Virtual Filesystems

There are four (4) kinds of different virtual filesystems supported in the server:

  • Tftproot server - serves files from a folder on the filesystem.
  • HTTP proxy server - serves files from a remote HTTP server.
  • Grandstream firmware server - serves firmwares to Grandstream VoIP phones.
  • Grandstream provisioning server - serves provisioning files to Grandstream VoIP phones.

In the configuration file you can find the bean with id "vfs". This bean holds a list of the enabled filesystems in the Tftpd server. You can add/remove from the list as you like. An example shows:

<bean id="vfs" class="net.tanesha.tftpd.core.Vfs">
	<property name="filesystems">
		<list>
			<ref local="firmwareServer"/>
			<ref local="provisionServer"/>
			<!--
				http proxy server is disabled
				<ref local="httpProxyServer" />
			-->
			<ref local="tftprootServer"/>
		</list>
	</property>
</bean>

The order of which you configure the filesystems is important. Each virtual filesystem serves different kinds of files. The first filesystem to return a file will be the file served to the user. For example, if you configure tftprootServer as the first filesystem in the list, and a file cfg00123456789 exists, then this will be served instead of the file provided by the provisionServer later.

Configuration of Tftproot server

This filesystem serves files from a folder specified in the rootpath property. It matches all files and looks in the specified directory for files. If a file is found, it is served.

<bean id="tftprootServer" class="net.tanesha.tftpd.vfs.TftpRootServer">
	<property name="rootpath" value="/tftpboot" />
</bean>

Configuration of HTTP proxy server

This serves files from a remote HTTP server. It is using the pattern to describe which files should be served. Some macros are available for putting into the target URL:

  • %f - filename requested.
  • %m - MAC address (extracted only from Grandstream phones).
 	<bean id="httpProxyServer" class="net.tanesha.tftpd.vfs.HTTPProxy">
		<property name="pattern" value="^/?cfg[0-9a-f]{12}$"/>
		<property name="target" value="http://voip/cgi-bin/tftp_request.cgi?mac=%m"/>
	</bean>

Configuration of Firmware server and Provision Server

Firmware needs the external interface to find information about the client and what firmware should be served.

	<bean id="firmwareServer" class="net.tanesha.tftpd.vfs.FirmwareServer">
		<property name="tftpdExternalInterface" ref="tftpdExternalInterface" />
		<property name="versioningHelper" ref="versioningHelper" />
	</bean>

Provisioning need the external interface to find information about the client and what provisioning settings should be served.

	<bean id="provisionServer" class="net.tanesha.tftpd.vfs.ProvisionServer">
		<property name="tftpdExternalInterface" ref="tftpdExternalInterface" />
	</bean>

JDBC external settings

Should be configured in config.xml as follows:

<bean id="tftpdExternalInterface" class="net.tanesha.tftpd.jdbc.JdbcExternalImpl">
	<property name="datasource" ref="myJdbcDatasource" />
	<property name="queryByVersion">
		<value>
			select phone_id, version_no, firmware_path from firmware_versions where phone_id = ? and version_no = ?
		</value>
	</property>
	<property name="queryLatestVersion">
		<value>
			select phone_id, version_no, firmware_path from firmware_versions where phone_id = ? and is_latest = 'T'
		</value>
	</property>
	<property name="queryPhoneByMac">
		<value>
			select phone_id, version_no from phone_firmwares where mac_address = ?
		</value>
	</property>
	<property name="querySettingsByMac">
		<value>
			select provision_attribute, provision_value from phone_settings where mac_address = ?
		</value>
	</property>
</bean>

<!-- please refer to spring documentation www.springframework.org for how to configure a datasource for your database -->
<bean id="myJdbcDatasource" class="...">
</bean>

After that you should be able to start your tftpd-server and see that it connects to your database and is using settings from it.

Database layout

The queries above are matching a database layout as follows:

create table firmware_versions (
	phone_id varchar(50),
	version_no varchar(50),
	firmware_path varchar(100),
	is_latest varchar(1),
	primary key (phone_id, version_no)
);

create table phone_firmwares (
	mac_address varchar(15) primary key,
	phone_id varchar(50),
	version_no varchar(50)
);

create table phone_settings (
	mac_address varchar(15),
	provision_attribute varchar(10),
	provision_value varchar(100),
	primary key (mac_address, provision_attribute)
);

But, you can modify the SQL to match any existing schema you may have.

Contributors

The following people have contributed, a BIG THANKS from here:

  • Steven Carey (Personal)

  • Johathan Owens (Personal)

About

Grandstream unofficial TFTP provisioning server.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published