Sunday, February 27, 2011

Androidified

I picked up a Motorola Xoom tablet on February 24th, the day of its release. To start with, the Xoom is equipped with a Dual-Core ARM Cortex A9 processor called the Nvidia Tegra 2. The Xoom runs Android 3.0, Honeycomb. There are no third party UI replacements or additions. The Xoom runs pure Android 3.0 and it is very fast.

One of the nice things that you can do is customize the keyboard. For a 10 inch tablet, it is convenient to be able to type with your left and right thumbs and Thumb Keyboard is available on the Android Marketplace just for this.

Thumb Keyboard greatly speeds up typing on the Xoom.

Next, let's build a statically linked Busybox binary so that you can do something useful with the device.
# wget http://busybox.net/downloads/busybox-1.18.3.tar.bz2
# wget http://www.busybox.net/downloads/busybox-1.18.3.tar.bz2.sign
# http://busybox.net/~vda/vda_pubkey.gpg
# gpg --check-sigs vda.linux
# gpg --verify busybox-1.18.3.tar.bz2.sign
# sha1sum busybox-1.18.3.tar.bz2
# md5sum busybox-1.18.3.tar.bz2
# bzip2 -cd busybox-1.18.3.tar.bz2 | tar xf -
# cd busybox-1.18.3

# make ARCH=arm CROSS_COMPILE=arm-linux-gnueabi- defconfig
# make CFLAGS=--static LDFLAGS=--static ARCH=arm CROSS_COMPILE=arm-linux-gnueabi-
# adb remount
# adb push busybox /system/xbin/busybox
# adb shell chmod 0755 /system/xbin/busybox
# adb shell
# cd /system/xbin
# ./busybox --install -s /system/xbin
# cd /mnt/sdcard
# echo "export PATH="export PATH=/system/xbin:/sbin:/vendor/bin:/system/sbin:/system/bin" > profile
# echo "ENV=/mnt/sdcard/profile /system/xbin/ash" > /system/bin/alsh
# chmod 0755 /system/bin/alsh
# alsh
# uname -ia
# Linux localhost 2.6.36.3-g2a65edc #1 SMP PREEMPT Mon Feb 7 15:24:33 PST 2011 armv7l GNU/Linux

Saturday, July 31, 2010

Agile Data modeling, de-normalization, and other important factors

This subject probably deserves an entire book, but in the essence of keeping this blog post short, I've tried to highlight some of the more important data modeling tasks related to conceptual, logical, and physical data model design. Please note, this is not meant to be exhaustive. Relational models, object-relational models, and object models are not always the right solution for the problem. There are many great solutions available in the NoSQL area, and there is nothing wrong with a hybrid solution.

Software applications that are compiled on specific machine architectures often store and retrieve information from database software systems. Web server platforms often interpret machine-independent script that stores and retrieves information from database software systems. Java bytecode is executed by a Java Virtual Machine, and data is stored and retrieved from database software systems.

Efficient storage and retrieval of information from database software systems are certainly dependent on underlying hardware and operating system software characteristics. However, efficient storage and retrieval of information is also dependent on the structure and efficient execution of query statements that are used to store and retrieve the information. In a purely academic world, data is modeled and normalized in 3NF, 4NF, and 5NF forms. However, higher-order normalized forms do not always promote the creation of optimal query statements. Therefore, certain parts of a data model are often denormalized to improve the read performance of the database software system.

At a high level, joins between multiple, large relations are generally expensive, so denormalization reduces this cost. Reducing the cost of something typically results in inconsistencies or redundancies in the data, so the developer(s) are left with the job of minimizing the amount of redundant data. A formal process typically alleviates this strain.

Defining the I/O characteristics of a database is an important precursor to data modeling. Often times, the I/O characteristics of the database are not defined before modeling the data. Nevertheless, there are a few basic tasks and questions that can help define the I/O characteristics of the database. What is the purpose of the database and what types of problem(s) does the database solve? What types of operations (read, write) will be performed on the database? How many users will the database support? Define user stories - short, succinct 1-3 sentence action statements. Define as many as needed from both the developer perspective and the user perspective. The user stories will help define the conceptual data model for the domain from which the logical data model can be created. A clear definition of the purpose of the system will aid in defining the read/write (I/O) characteristics of the database software system, thus forming a picture of the system. For instance, OLTP databases typically support short transactions, so it is important that write latency is minimized. The answers to the questions above will also help determine the type of hardware storage configuration needed. Another important question when determining the type of hardware configuration is the following. How much downtime can be afforded, and how much failover is needed?

At this point, the types of queries can be seen that will be run on the database with heavy consideration given to the I/O characteristics of the database and the types of joins and scans preferred for the query optimizer to ideally use.

Agile data modeling can be defined as continual iterative feedback with the ability to add entities and relationships, or slice off sections of a data model in various sizes, at any point in the project. This may seem difficult but can be accomplished. Whether the database architecture adheres to the relational model, object-relational model, or object model, the proper classification of entities and attributes, in conjunction with a balance of normalized and de-normalized groups of data, will allow the addition and subtraction of small and large chunks of relations from the data model throughout the development process; for a specific domain. Formal algorithms can be used to map entity relationship models to relations.

And how is this done? Continually modeling entities within the real world. Abstracting classes, re-factoring, keeping the hierarchy semi-flat, avoiding deep polymorphic behavior, and always embracing changes to the data model while never generalizing with a one size fits all approach.

It's important to note that data modeling is a crucial step in designing a database software system that efficiently stores and retrieves information. This process involves defining the I/O characteristics of the database, understanding the purpose of the system, and creating a conceptual data model for the domain. From there, a logical data model can be created, followed by a physical data model that considers the hardware storage configuration needed. Agile data modeling allows for continual iterative feedback, and the proper classification of entities and attributes, in conjunction with a balance of normalized and de-normalized groups of data, will allow for the addition and subtraction of small and large chunks of relations from the data model throughout the development process. Overall, data modeling is a critical aspect of creating an efficient and effective database software system.

Close to Optimal Data Modeling

Agile Data modeling, de-normalization, and other important factors

This subject probably deserves an entire book but in the essence of keeping this blog post short, I've tried to highlight some of the more important data modeling tasks related to conceptual, logical, and physical data model design. Please note, this is not meant to be exhaustive. Relational models, object relational models, and object models are not always the right solution for the problem. There are many great solutions available in the noSQL area and there is nothing wrong with a hybrid solution.

Software applications that are compiled on specific machine architectures often store and retrieve information from database software systems. Web server platforms often interpret machine independent script that stores and retrieves information from database software systems. Java byte code is executed by a Java Virtual Machine and data is stored and retrieved from database software systems.

Efficient storage and retrieval of information from database software systems is certainly dependent on underlying hardware and operating system software characteristics. However; efficient storage and retrieval of information is also dependent on the structure and efficient execution of query statements that are used to store and retrieve the information. In a purely academic world, data is modeled and normalized in 3NF, 4NF, and 5NF forms. However; higher order normalized forms do not always promote the creation of optimal query statements. Therefore, certain parts of a data model are often de-normalized to improve the read performance of the database software system. At a high level, joins between multiple, large relations are generally expensive so de-normalization reduces this cost. Rreducing the cost of something typically results in inconsistencies or redundancies in the data so the developer(s) is left with the job of minimizing the amount of redundant data. Formal process typically alleviates this strain.

Defining the I/O characteristics of a database is an important precursor to data modeling. Often times, the I/O characteristics of the database are not defined before modeling the data. Nevertheless, there are a few basic tasks and questions that can help define the I/O characteristics of the database. What is the purpose of the database and what types of problem(s) does the database solve? What types of operations (read, write) will you be performing on the database? How many users will the database support? Define user stories - short, succinct 1-3 sentence action statements. Define as many as you need from both the developer perspective and the user perspective. The user stories will help define the conceptual data model for the domain from which the logical data model can be created. A clear definition of the purpose of the system will aid in defining the read/write (I/O) characteristics of the database software system. Thus forming a picture of the system. For instance, OLTP databases typically support short transactions so it is important that write latency is minimized. The answers to the questions above will also help determine the type of hardware storage configuration needed. Another important question when determining the type of hardware configuration is the following. How much downtime can we afford and how much failover do we need?

At this point, we can begin to see the types of queries that will be run on the database with heavy consideration given to the I/O characteristics of the database and the types of joins and scans that we would like for the query optimizer to ideally use.

Agile data modeling - Continual, iterative feedback. The ability to add entities and relationships, or slice off sections of a data model in various sizes, at any point in the project. This may seem difficult but can be accomplished. Whether the database architecture adheres to the relational model, object-relational model, or object model, the proper classification of entities and attributes, in conjunction with a balance of normalized and de-normalized groups of data, will allow the addition and subtraction of small and large chunks of relations from the data model throughout the development process; for a specific domain.

Formal algorithms can be used to map entity relationship models to relations.

And how is this done? Continually modeling entities within the real world. Abstracting classes, re-factoring, keeping the hierarchy semi-flat, avoiding deep polymorphic behavior, and always embracing changes to the data model while never generalizing with a one size fits all approach.

Saturday, July 24, 2010

High Performance Database Development

Fast, High performance, database driven, application architectures that support true rapid development are little talked about. AOLServer, OpenACS, PostgreSQL, and TCL are such a combination.

I was introduced to AOLServer and OpenACS in 2002 by a close friend who I grew up with. We built a very robust application architecture over the course of the following 6 years.

PostgreSQL was sitting behind the AOLServer/OpenACS instance and AOLServer nicely managed the database connection pools. AOLServer is multi-threaded and internally handles TCL interpretation and execution. TCL makes heavy use of lists (implementation notes aside), so many LISP programmers have enjoyed working with it.

The OpenACS developer toolbar is a tool that provides developers with access to various debugging and profiling information about their OpenACS application. It is a feature that is built into the OpenACS application framework and can be enabled or disabled depending on the needs of the developer.

Once enabled, the developer toolbar is accessible via a web browser and provides a range of information about the current page, including SQL queries, response times, and server resources. This information can be used to optimize and debug an OpenACS application, allowing developers to quickly identify and fix performance issues.

The OpenACS developer toolbar is just one of the many tools available to developers using the AOLServer, OpenACS, PostgreSQL, and TCL stack. Together, these technologies provide a fast, high-performance, database-driven application architecture that supports rapid development.

Tuesday, July 20, 2010

Dtrace on FreeBSD 8

 Dtrace on FreeBSD 8 - new server with no load

# uname -msri
FreeBSD 8.0-RELEASE-p3 amd64 DEV_A64_KERNEL

From the OpenSolaris DTrace Toolkit

# /usr/local/share/DTTraceToolkit/syscallbypid.d
Tracing... Hit Ctrl-C to end.
  77913 perl                     sigprocmask                    48
  1267 svscan                   stat                           51
 45001 httpd                    read                           52
 26063 python2.4                recvfrom                       61
 26922 sshd                     ioctl                          69
 27104 more                     read                           69
 26888 postgres                 getppid                        78
 26888 postgres                 gettimeofday                   78
 26888 postgres                 select                         78
 26889 postgres                 getppid                        78
 26889 postgres                 select                         78
 45001 httpd                    poll                           81
 27102 postgres                 read                           82
 27103 postgres                 read                           82
 27105 postgres                 read                           82
 27101 dtrace                   clock_gettime                  97
 26063 python2.4                select                        102
 45001 httpd                    writev                        118
 44966 python2.4                read                          121
 26890 postgres                 read                          162
 26063 python2.4                read                          179
 26063 python2.4                _umtx_op                      186
 27104 more                     write                         205
 26063 python2.4                write                         208
 26891 postgres                 write                         300
 27101 dtrace                   ioctl                         301
 26922 sshd                     write                         304
 26922 sshd                     read                          306
 27054 psql                     poll                          378
 27054 psql                     recvfrom                      378
 27055 postgres                 sendto                        379
 26922 sshd                     select                        609
 26922 sshd                     sigprocmask                  1218
 27054 psql                     write                        3203

 

# /usr/local/share/DTTraceToolkit/rwbypid.d
78168  sshd                        R       39
 97062 squid                       R       58
 45164 httpd                       W       81
 97062 squid                       W       95
 97474 python2.4                   R       98
   555 pflogd                      R      132
 45164 httpd                       R      186

 

# dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'

CPU     ID                    FUNCTION:NAME
  0  25202                       open:entry svscan .
  0  25202                       open:entry imapd ./cur
  0  25202                       open:entry imapd ./new
  0  25202                       open:entry imapd ./courierimapkeywords/:list
  0  25202                       open:entry imapd ./courierimapkeywords
  0  25202                       open:entry svscan .
  2  25202                       open:entry postgres pg_stat_tmp/pgstat.tmp
  7  25202                       open:entry postgres global/pg_database
  7  25202                       open:entry postgres pg_stat_tmp/pgstat.stat
  7  25202                       open:entry postgres pg_stat_tmp/pgstat.stat
  7  25202                       open:entry postgres pg_stat_tmp/pgstat.stat
  4  25202                       open:entry tinydns data.cdb
  5  25202                       open:entry tinydns data.cdb
  0  25202                       open:entry svscan .
  0  25202                       open:entry svscan .
  0  25202                       open:entry svscan .
Syscalls count by process

# dtrace -n 'syscall:::entry { @num[pid,execname] = count(); }'
 28820  qmailmrtg7                                                      158
    28825  qmailmrtg7                                                      158
    27504  postgres                                                        159
    28776  cron                                                            234
    28853  bash                                                            245
    28861  bash                                                            245
    28869  bash                                                            245
    28877  bash                                                            245
    28798  qmailmrtg7                                                      264
    28777  newsyslog                                                       293
    28772  dtrace                                                          322
    28778  sh                                                              327
    28281  httpd                                                           542
    28900  svn                                                             691
    28903  svn                                                             740
    28902  svn                                                             748
    28904  svn                                                             748
    28901  svn                                                             758
    28780  perl                                                           3023

 

# Files opened by process
dtrace -n 'syscall::open*:entry { printf("%s %s",execname,copyinstr(arg0)); }'
CPU     ID                    FUNCTION:NAME
  4  25202                       open:entry svscan .
  0  25202                       open:entry squid /usr/local/plone/<domain-name>-dev.com/var/squidstorage/08/0C
  4  25202                       open:entry svscan .
  4  25202                       open:entry svscan .
  4  25202                       open:entry svscan .
  0  25202                       open:entry imapd ./.Spam/tmp/1279591336.M11620P234573_courierlock.dev.<domain-name>.com
0 25202 open:entry imapd ./.Spam/tmp/1279591336.M11620P234573_courierlock.dev.<domain-name>.com
0 25202 open:entry imapd ./.Spam/tmp 0 25202 open:entry imapd ./.Spam/tmp/1279591336.M11867P28573_imapuid_15.dev.<domain-name>.com
0 25202 open:entry imapd ./.Spam/courierimapuiddb 0 25202 open:entry imapd ./.Spam/tmp/1279591336.M113467P28573_imapuid_15.dev.<domain-name>.com 0 25202 open:entry imapd ./.Spam/cur 0 25202 open:entry imapd ./.Spam/new 0 25202 open:entry imapd ./.Spam/courierimapkeywords/:list 0 25202 open:entry imapd ./.Spam/courierimapkeywords 0 25202 open:entry squid /usr/local/plone/abcdexcrfdsf-dev.com/var/squidstorage/09/0C 4 25202 open:entry svscan .

Thursday, May 27, 2010

bsdtalk186 - Soft Updates w/ Journaling & ULE Sched

FreeBSD Soft Updates with Journaling, ULE Scheduler

Very good short interview with Jeff Roberson, FreeBSD Committer.Discussion on the addition of journaling to soft updates and the development of the ULE scheduler.

BSD Talk Blog - Jeff Roberson (February 05, 2010)

You can also listen on your Android device. Just download Google Listen from the marketplace. After you setup Google Listen on your Android Device, search for bsdtalk or FreeBSD from within Google Listen.

Wednesday, May 5, 2010

Single Thread Object Communication

When objects in a single thread are loosely coupled and need to communicate with each other, Notifications allow you to broadcast messages on a synchronous or asynchronous basis and still retain object independence.

When you implement Store Kit in your application, it is most likely a reasonable assumption that you want to re-use your in-app store in a future iPhone application without rewriting the object(s) that implement the SKPaymentTransactionObserver and SKProductsRequestDelegate protocols. We know that these objects receive asynchronous notifications via the delegate protocol(s) that they implement. So in a nutshell, the object that implements the SKProductsRequestDelegate protocol will receive a response asynchronously when the product identifier request that it previously sent is successfully processed. The payment transaction observer object, which is added as an observer to the payment queue upon application launch, again receives asynchronous notifications when there's stuff to do in the payment queue.

When your transaction observer receives notifications from the payment queue that there are updated transactions, completed transactions, or failures, it is most likely the responsibility of the observer object to process these notifications. The processing of these notifications most likely entails application specific logic. So rather than loading up your transaction observer with application specific logic, the NSNotification center provides a clean way of synchronously or asynchronously(via Notification Queues) notifying other objects within the same thread. There is also an NSDistributedNotificationCenter for broadcasting messages to objects in other threads.

By using the NSNotification center, you can separate the application-specific logic from the observer object that receives notifications from the payment queue. This allows for a cleaner and more modular design, as each object can focus on its specific responsibilities without being tightly coupled to other objects. In addition, the NSNotification center provides a flexible way to communicate between objects within the same thread or across different threads using the NSDistributedNotificationCenter. This makes it easier to reuse and refactor code, which can save time and effort in the long run.

Monday, May 3, 2010

Creating a Mobile App for the iPhone

In the coming weeks, I plan on covering the development process from start to finish. I will be talking about code organization, memory management, useful xcode features, core data, performance optimization, debugging, iterative development, and any other useful topics that I come across.

iLogMiles was approved by Apple for sale on the App store, on April 6, 2010. iLogMiles is free to download. The app quickly hit the #2 spot on the top free business apps list. The user can upgrade to the full version and purchase themes from within the free application. We utilized the Apple Store Kit framework to provide the in-app store. The Store Kit framework provides the necessary means to securely process payments from within the application. Products are identified via product identifiers. Apple clearly defines the types of products that may be sold via the Store Kit framework. More on this later but keep in mind that it is very important to read through all of the documentation.

Over the next few weeks, we will be talking about the mobile application development process. To give you some background on me, I started with C++ in 1997. At the time, I mostly used the GNU compilers on FreeBSD and Linux and Sun workshop on a SPARCstation. And for the C++ courses I was taking, Borland in a Win environment. To get up to speed on iPhone OS, I purchased the WWDC 2009 sessions and watched them all (at the gym on my iPhone). I attended the iPhone tech talk tour in San Jose and I listened to any and all of the available iPhone development podcasts (at the gym) that I could find. I poured through all of the books that I could get my hands on. I read the iPhone OS programming guides on the iPhone OS developer connection. XCode also has integrated documentation for the Apple API's. I've always used vi/vim with ctags, so I had to force myself to watch the xcode screencasts (available via third-party on the Internet). There are lots of great xcode tips out there and you can print out a summary page with all of the cute shortcuts - if you are so inclined to do so. I found it quite helpful to print the shortcuts page.  Design patterns are at the core of how the Cocoa frameworks interact. Apple provides solid documentation on Cocoa design patterns in the iPhone OS Reference Library and these patterns can be understood at a high-level without delving into any code. This is my suggested approach. If you are not familiar with design patterns, the gang of four book (the GOF book as most often termed in the software world) - Design Patterns: Elements of Reusable Object-Oriented Software, by Erich Gamma, Richard Helm, Ralph Johnson, and John Vlissides, is the official source for design patterns. The theory behind Cocoa's design patterns can be found in this book and for that matter, the use of design patterns in any modern object-oriented software system can be found in this book. The GOF book describes design patterns in a language independent manner. Familiarizing yourself with Cocoa's design patterns from a language independent perspective is a key starting point for building an iPhone application.

Continuing on the topic of cocoa design patterns, Apple's frameworks are designed for re-use. There are folks out there who are very experienced with design patterns and are able to layer design patterns on top of the cocoa frameworks. These individuals understand all of the memory implications. They understand MVC backward and forward and they understand the Cocoa design patterns backward and forward. If you do not fall into this category, then keep it simple. If there is one problem that I have seen across forums and code samples on the Internet, it is that of "fighting the apis". It is very important to not fight the apis. The apple documentation describes the proper use of the iPhone OS frameworks and associated API's. The Apple developer connection provides plenty of sample code so it is important to read through this code to understand the proper use of the iPhone OS APIs.

From inception to app store approval, we spent 5 months developing iLogMiles. While this may seem longer than the standard "2 month" development lifecycle, I can assure you that iLogMiles uses a wide variety of the iPhone OS frameworks. In the coming weeks, we plan on covering the development process from start to finish. I will be talking about code organization, memory management, xcode features, core data, performance optimization, debugging, iterative development, and any other topics that we see useful.

Apple, the Apple logo, iPhone, iPod touch, and iTunes are trademarks of Apple Inc., registered in the U.S. and other countries. iPad is a trademark of Apple Inc. App Store is a service mark of Apple Inc.

Monday, February 1, 2010

Objective-C Categories

Categories are a powerful tool for extending the functionality of existing classes in Objective-C. However, it's important to follow Apple's guidelines when using them to avoid any undefined behavior.

Categories allow you to extend the functionality of an existing class without subclassing. Before I get into an example, here are a few guidelines to follow when using categories. Apple recommends to not use categories to override methods in other classes, inherited classes, or other categories. Categories are not meant to add instance variables to classes either. If used in such contexts, the behavior of a program is undefined. Apple recommends using categories for adding functionality to large, existing classes and then grouping that functionality accordingly. Overriding existing Cocoa methods that are inherited from within the Cocoa hierarchy is a no-no as is extending methods that are already part of a category within the Cocoa hierarchy. Categories allow the addition of methods to existing classes while retaining the scope of class instance variables. So here's an example. Categories are quite simple to create and very powerful.

myCategory.h
@interface UIViewController(myCategory)
- (void)messageName:(double)arga keywordA:(double)argb keywordB:(NSString *)argc;
myCategory.m
#import "myController.h"

@implementation UIViewController(myCategory)
- (void)messageName:(double)arga keywordA:(double)argb keywordB:(NSString *)argc {
// process arguments
// do something with ivar
// ...
}
myController.h
#import "myCategory.h"
@interface myController : UIViewController {

   someType ivar;
}

- (void) someMessage;
...
@end
myController.m
#import "myController.h"

@implementation

- (void)someMessage {

   [self messageName];  // send message to self - i.e. call method defined by category
}

@end

Monday, January 25, 2010

Core Data

I was fortunate to attend the iPhone Tech Talk conference, hosted by Apple Inc. in San Jose last October, 2009. One of the sessions I attended was on Core Data. At a very high level, Core Data is an Apple™ software framework for storing data on the computer - namely, the iPhone and the Mac. Please note that I don't plan on covering database design theory in this post so I'm assuming a familiarity with it.

Core data is an Object graph management and persistence framework. Core data maintains a graph of objects (otherwise known as a managed object graph or managed object context). References to managed objects are stored in the object graph. Core Data serializes these objects and persists them to a data store. Core data can use several different underlying data stores - xml, binary, sqlite. The managed object context is a key concept in Core Data, as it provides a proxy between the application objects and the underlying data store(s). The persistent store coordinator is responsible for managing the relationship between the managed object context and the persistent store(s). A managed object context wraps a collection of managed objects and sits on top of a persistent store coordinator which houses one or more persistent stores. A managed object context is created via an instance of the NSManagedObjectContext class.

It's important to note that the Core Data sqlite file should not be accessed directly from within code, as the schema may change and it's not intended for direct manipulation.

In Summary, a managed object context is a collection of managed objects. Managed objects are instances of the entities that are defined in the data model. A managed object represents a row of data in a table. The managed objects context sits on top of a persistent store coordinator. The managed object context is a proxy between the objects in the application and the underlying data store(s). A persistent object store is represented by a xml, binary, or sqlite file. The persistent store coordinator sits between the managed object context and the persistent store(s). The persistent store coordinator in turn abstracts one or more persistent object stores as a single aggregate. Please note, a persistent store coordinator can only be associated with one managed object context. But a persistent store coordinator can have many persistent object stores. The managed object context talks directly to the persistent store coordinator. The managed object context is a scratchpad of managed objects.
After working with Core Data, it is a worthwhile exercise to open the core data sqlite file and dig through the tables. A quick look through the tables will explain how Apple is handling referential integrity. The Core Data sqlite file is "not meant" to be accessed directly from within code. Do not modify it or attempt to write queries against it. There is no guarantee that the schema will not change. Core Data is meant to abstract implementation dependent details (i.e. the implementation may change upon any future releases).

The following notes were derived from three sources: Apple WWDC 2009, the iPhone Core Data session in San Jose last October, and my experience working with object/relational databases.

Creating a Core Data Stack

  1. Load the Data Model
  2. Create the persistent store coordinator and set the model
  3. Add the data store
  4. Create a managed object context and set the persistent store coordinator

Core Data Model

  1. A Core Data model does not need to be normalized. Define data contracts early on. Don't over tighten the data model - design with usage patterns in mind. Define entities or tables with Xcode's visual editor. (core data objects represent rows in these tables). In other words, a Core Data object (row of data) of type PERSON is an instance of the PERSON entity in the Core Data model. Of course, a person object will have relationships with other objects in the database. A Core Data Managed object context manages these objects, their relationships, and persists them to the underlying data store (via the persistent store coordinator). Core Data is simple to setup. Don't complicate it.
  2. NSManagedObjectContext defines the verbs (CRUD or fetch/insert/delete/save) that act on managed objects (nouns)
  3. NSManagedObjectContext tracks changes to properties in the data model
  4. Core Data fits very well in the MVC architecture.
  5. An NSPersistentStoreCoordinator can have multiple persistent stores(NSPersistentStore) and multiple Managed Object Contexts can use a single NSPersistentStoreCoordinator
  6. It is possible to delete the sqlite store file if the stored data needs to be deleted. This file is stored in $HOME/Library/Application Support/iPhone Simulator/User/Applications/SOMEAPPLICATIONGUID/Documents
  7. Use Core Data migration or built-in versioning for model changes. easy to use. zero code.

Multithreading

  1. Core data assigns one managed object context per thread; use notifcations for changes made to managed objects within a managed object context.
  2. never pass managed objects between threads, pass object IDs (actually the primary key)
  3. within a thread, create a new Managed object context and then tell the new Managed object context what objects IDs to fetch

Fetching

    Use NSFetchedResultsController (break up fetches into sections) - it is fast, efficient, and easy.
  1. Create an NSFetchedResultsController
  2. Set the fetch request, predicate, and sort descriptors. fetch request provides predicate and sort descriptors). fetch request and predicate are immutable.
  3. the keypath returns the section name (section information is cached)
  4. set yourself as its delegate and implement your tableview methods
  5. Create separate controllers for different data sets

NSFetchRequest

  1. set the entity that you want to fetch against
  2. create NSEntityDescription - provide managed object context and entity you want to work with
  3. set the predicate (if applicable)
  4. Fetch - pass in fetch and error

Batching

  1. setup fetch request (only need some of the objects at a time so setBatchSize:)
  2. set batch size
  3. you get back an NSArray of results

Prefetching

  1. use setRelationshipKeyPathsForPrefetching:

Managed Object Interaction

    NSManagedObject
  1. Use accessors
  2. Objective-C properties
  3. To Many relationships are sets
  4. NSManagedObjects provides Key value coding/observing out of the box
  1. Managed Object Context observes object changes. Leverage change tracking notifcations
  2. Register for Object Level Changes (KVO)
  3. Register for Graph Level Changes (NSNotifications)


Sunday, January 24, 2010

Iterate over Custom UITableViews

UITableViews on the iPhone often contain a variable number of cells. The following code snippet should be helpful for those who need to iterate over a variable length table and subsequently read or set data model and cell state.
   //loop through cells in each section and make sure the data model is in sync 
   NSInteger numSections = [self numberOfSectionsInTableView:someTable];
   for (NSInteger s = 0; s < numSections; s++) { 
      NSLog(@"Section %d of %d", s, numSections); 
      NSInteger numRowsInSection = [self tableView:someTable numberOfRowsInSection:s]; 
      for (NSInteger r = 0; r < numRowsInSection; r++) {
         NSLog(@"Row %d of %d", r, numRowsInSection); 
         MyCell *cell = (MyCell *)[someTable cellForRowAtIndexPath: 
                                  [NSIndexPath indexPathForRow:r inSection:s]]; 
         DataModelObject *theObject = (DataModelObject *)[fetchedResultsController objectAtIndexPath:
                                                         [NSIndexPath indexPathForRow:r inSection:s]]; 
         [theObject setValue:[NSNumber numberWithBool:MyCell.someProperty] forKey:@"someEntityKey"]; 
      } 
   }


Monday, December 7, 2009

Mobile Technology - Where Are We Going?

OS X and iOS contain open source components.
  1. Open Source Components that ship with Mac OS X 10.6.2 and their corresponding Open Source Projects (src avail for dl/browse) - http://www.apple.com/opensource/
  2. Open Source Components that ship with Mac OS X 10.6.2, iPhone OS 3.1.2 and Developer Tools 3.2.1 (source avail for dl) Also browseable by prior versions - http://opensource.apple.com
The open source components are typically released under various open source licenses, such as the Apache License, the GNU General Public License, and the BSD License, among others. By including open source components, Apple is able to leverage the work of the open source community and provide a more robust and secure platform for its users. The open source components can also be used by developers to build applications for macOS and iOS, as well as for other platforms.

On to Android...so what is it? Android is an open-source mobile operating system. It uses a modified Linux 2.6 Kernel - tuned for embedded devices. To quote the Android Web site - "Android relies on Linux version 2.6 for core system services such as security, memory management, process management, network stack, and driver model. The kernel also acts as an abstraction layer between the hardware and the rest of the software stack." (http://developer.android.com/guide/basics/what-is-android.html).

Linux is known for its stability, security, and flexibility. It has become a popular choice for servers, workstations, and even desktops. Linux is widely used in the cloud computing industry and powers many of the world's largest websites and services. It has a strong developer community and a vast selection of open-source software available for free. Additionally, Linux is highly customizable, allowing users to modify and tailor their operating system to their specific needs.

Linux (GNU/Linux) is a UNIX-like operating system that comes in many flavors or distributions. The distributions typically differ in how package (applications) distribution is handled. Oftentimes, a custom or stripped down kernel is shipped with the distribution. There are over 600 GNU/Linux distributions. They run on a myriad of devices from embedded controllers to large scale grids and supercomputers.  GNU/Linux has been around a while - Linuz Torvalds coined the term in '91. The GNU Project, created by Richard Stallman in 1983, had the goal of creating a complete Unix-compatible software system composed entirely of free software". Hence came GNU/Linux. Read more here - http://www.gnu.org/.

To clarify, the GNU/Linux operating system consists of the Linux kernel (created by Linus Torvalds in 1991) and GNU software, which was developed by the GNU Project (launched by Richard Stallman in 1983) and includes tools such as the GNU C Compiler (GCC), GNU Debugger (GDB), and Bash shell.

The Linux kernel was based on the Minix operating system and Unix principles, but it was not directly derived from SVR4 or BSD. It was created as a free and open-source alternative to commercial operating systems and has since become widely used on servers, desktops, and mobile devices.

The process, thread, and memory models in GNU/Linux are based on the Unix principles and have been tested and refined over several decades. They are known for their stability and scalability, making GNU/Linux a popular choice for high-performance computing and enterprise applications.

Many GNU userland tools, such as Bash, GCC, GNU coreutils, and GNU Emacs, are included in most GNU/Linux distributions. These tools are often used by developers and system administrators to perform various tasks, such as writing and compiling code, managing files and directories, and configuring system settings. The availability of these tools on GNU/Linux systems is a result of the close relationship between the GNU Project and the Linux kernel.

Android uses a modified version of the Linux kernel, which is a Unix-like operating system kernel, but its userland libraries are not based on GNU/Linux. Instead, Android uses a custom, BSD-like userland developed by Google. This allows Android to have more control over the code and reduce dependencies on GNU/Linux. However, Android still maintains compatibility with many GNU/Linux tools and libraries.

As opposed to Objective-C, which developers use to write applications for the iPhone, Java is used for writing applications on Android devices. Android provides libraries on top of the kernel for 2D and 3D rendering, type support, sqlite access, media, libc (actually called Bionic), etc. While the Linux kernel provides memory management, process and threading support, etc., Google uses a byte-code interpreter (well, not exactly, but similar) called DalvikVM which transforms java class files into a second type of byte code format - .dex. An Android application gets loaded into a single process and is allocated a DalvikVM instance. DavlikVM was chosen because of its memory/processor efficiency on embedded devices.

Android also provides an application framework that allows developers to use various pre-built components such as activities, services, content providers, and broadcast receivers to build their applications. These components help developers to manage the lifecycle of their applications and handle various system events, such as incoming phone calls or text messages.

The Android SDK (Software Development Kit) provides all the necessary tools and libraries for developers to build, test, and debug their applications. The SDK includes an emulator, which allows developers to test their applications on a virtual device before deploying them on an actual Android device.

In addition, Android is built with security in mind. It includes various security features such as app sandboxing, which isolates each application and its data from other applications, and permissions, which allow users to control what data and resources an application can access on their device.

In 2007, Google created the open handset alliance with the following objective: "The Open Handset Alliance is a group of 47 technology and mobile companies who have come together to accelerate innovation in mobile and offer consumers a richer, less expensive, and better mobile experience. Together we have developed Android™, the first complete, open, and free mobile platform. We are committed to commercially deploy handsets and services using the Android Platform (http://www.openhandsetalliance.com)". By working together, the alliance aims to create a more open and innovative mobile ecosystem that benefits both developers and consumers.

The list of member companies is huge including but not limited to, TI, NVidia, Quallcomm, Acer, Sprint, Toshiba, LG, etc. Shortly thereafter, in 2008, Google released the Android source code under an Apache license. This move attracted and will continue to attract top developers from all over the world who are comfortable with the Java programming language in a Linux type environment.

By releasing the Android source code under an Apache license, Google allowed developers to modify and distribute the code, which led to the creation of numerous custom ROMs (modified versions of the Android operating system) and a thriving community of developers. It also allowed manufacturers to use the Android operating system on their devices without any licensing fees, which helped to accelerate the adoption of Android.

Google's initiative with the release of the Android source code and the formation of the Open Handset Alliance were huge moves. The Open Handset Alliance will aid its member companies with deploying the Android operating system on their respective devices. In other words, we will see the Android operating system on many different brands of mobile phones.

The open-source nature of Android and the formation of the Open Handset Alliance have allowed for the widespread adoption of the Android operating system across many different mobile devices from various manufacturers. This has helped to create a more competitive and diverse mobile market, which ultimately benefits consumers.

By the end of 2009, there will be over 15 mobile devices with the Android operating system. There are over 15,000 apps on the Android market (as of November 2009). There were 10,000 apps on the Android Market 2 months ago. There are over 100,000 apps on the Apple app store (as of November 2009). The Apple app store is 16 months old. There have been over 2 billion total downloads since inception.

The Android operating system is solid and it isn't going anywhere. Here are some good resources on the Internet.

Getting Started with Android Development

The GNU Operating System

Free Software Foundation

Open Handset Alliance

What is Android?

Dalvik Virtual Machine insights

Android Notes

Inside the Android Application Framework

Saturday, April 4, 2009

FreeBSD remote kernel testing

FreeBSD 7 remote kernel testing

If the host is located at a remote location and is running a custom built kernel, then there is a handy feature in FreeBSD that will allow testing of the new kernel without breaking the entire system.

The commands (including the make command for the kernel) are as follows:

# cd /boot

# cp -R kernel kernel.good

# cd /usr/src

This will install the kernel in /boot/kernel

# make KERNCONF=MYKERNELNAME buildkernel

# cd /boot

# mv kernel kernel.mykernelname

# mkdir kernel

# cp kernel.good/* kernel/

# nextboot -k kernel.mykernelname

 

Upon reboot, the system will load kernel.mykernelname and then erase the part of the configuration that told it to load kernel.mykernelname.

Consequently, subsequent reboots will load the kernel located in /boot/kernel which is the original kernel.

Assuming that kernel.mykernelname loaded successfully, run the following commands to make the new kernel permanent:

# mv /boot/kernel /boot/kernel.previous

# mv /boot/kernel.mykernalname /boot/kernel

Friday, April 3, 2009

Plone and Apache on FreeBSD 7 behind PF

Plone 3.2.1 and Apache 2.2 on FreeBSD 7.2 behind PF

In 2001, PF was not yet integrated into the OpenBSD kernel.  OpenBSD 3.0 soon prevailed (2001) and PF was included in the kernel.  Soon thereafter (2003), PF was incorporated into the FreeBSD 5.3 kernel.   For those who are unfamiliar, PF is a system for filtering TCP/IP traffic and providing network address translation. However; PF also provides network traffic shaping capabilities - packet prioritization, bandwidth control, and TCP/IP conditioning.   My original article from 2000 explained how to setup an IP-less bridge on an OpenBSD 2.8 server running IP Filter  with dual network interface cards. The bridge filtered traffic at the data link layer and was invisible at the internet protocol level.  PF, like IP Filter, is very powerful.  While I will not be going into how to configure an IP-less bridge, the PF configuration that follows is straightforward and easily adaptable.

This document shows an example configuration of a PF ruleset and an Apache 2.2 installation in front of a Plone 3.2.1 instance on FreeBSD 7.2.  SSH tunnelling is used for remote management of the Zope/Plone instance (i.e. ZMI).

Pre-installation Requirements

  • FreeBSD 7.2-PRERELEASE w/ PF enabled
  • Apache 2.2 from (from ports) with mod_ssl (OpenSSL 0.9.8j), mod_proxy, and mod_rewrite
  • Zope w/ Plone 3.2.1
  • Varnish HTTP Accelerator

Zope is bound to an unprivileged port on localhost.  Apache is bound as a non-privileged user to port 80 and 443 on public IP address X.X.X.Y.  Zope/Plone can be running standalone or in a ZEO Server / ZEO client configuration.  In either case, Apache will function as a reverse proxy and send http requests to Zope.

Enable IP Forwarding in the Kernel

Enable IP forwarding in the kernel:

# sysctl net.inet.ip.forwarding=1
# sysctl net.inet.ip.fastforwarding=1
# sysctl net.inet6.ip6.forwarding=1

Add the following lines to /etc/sysctl.conf so that when the host is rebooted, IP forwarding is enabled:

# /etc/sysctl.conf

net.inet.ip.forwarding=1
net.inet.ip.fastforwarding=1
net.inet6.ip6.forwarding=1
kern.ipc.somaxconn=4096
kern.ipc.nmbclusters=32768

As an alternative, add the following to /etc/rc.conf

# /etc/rc.conf

gateway_enable="YES"

 

Enable HTTP Accept Filter

Next, make sure that the HTTP Accept filter is loaded into the kernel.

Check this by running the following command:

# kldstat

2 1 0xc0b12000 2464 accf_http.ko

If the filter is not loaded, edit /boot/loader.conf and add the following line so that when the host is rebooted, the HTTP Accept filter kernel module is loaded.

# /boot/loader.conf
accf_http_load="YES"

Last of all, to load the module without rebooting, run the following command:

kldload accf_http

 

System V Shared Memory and Semaphore Parameters

Modify System V shared memory and semaphore parameters

# sysctl kern.ipc.shmall=32768
# sysctl kern.ipc.shmmax=134217728
# sysctl kern.ipc.semmap=256

Make these changes permanent by adding the following to /etc/sysctl.conf

# /etc/sysctl.conf

kern.ipc.shmall=32768
kern.ipc.shmmax=134217728
kern.ipc.semmap=256
net.inet.ip.forwarding=1
net.inet.ip.fastforwarding=1
net.inet6.ip6.forwarding=0
kern.ipc.somaxconn=4096
kern.ipc.nmbclusters=32768

 

System V "Read-Only" Semaphore Parameters

Modify the System V "Read-Only" Semaphore Parameters by adding the following to /boot/loader.conf  

NOTE: Reboot for the new values of these parameters to take effect

# /boot/loader.conf

kern.ipc.semmni=256
kern.ipc.semmns=512
kern.ipc.semmnu=256
accf_http_load="YES"
net.inet.tcp.syncache.hashsize=1024
net.inet.tcp.syncache.bucketlimit=100
net.inet.tcp.tcbhashsize=4096
net.inet.tcp.syncache.cachelimit=102400

 

PF Configuration

# /etc/pf.conf
#

## MACROS-----
ext_if="bge0"
set loginterface $ext_if
local_networks = "{ a.a.a.b/24, c.c.c.d/24, e.e.e.f/26}"
internet_ports = "{80, 443}"

# Table Setup
# /etc/iface_addresses contains the following
# X.X.X.Y
# X.X.X.Z
table <iface_addresses> persist file "/etc/iface_addresses"
table <bruteforce> persist

# set Block Policy option
set block-policy return

# set Skip Filtering option on localhost
set skip on lo0

scrub in all
antispoof quick for $ext_if inet

# block ip addresses contained in bruteforce table
block in log (all, to pflog0) quick on $ext_if from <bruteforce> to any

# block and then log outgoing packets that don't have one of our IPs as the source IP
block out log (all, to pflog0) quick on $ext_if from ! <iface_addresses> to any

# block nmap scans
block in log (all, to pflog0) quick on $ext_if inet proto { tcp, udp } from any to any flags FUP/FUP

# block everything by default
block in on $ext_if all

# pass in icmp and keep state
pass in quick on $ext_if inet proto icmp all keep state

# pass in tcp traffic from localhost
pass in quick on $ext_if proto tcp from 127.0.0.1 to <iface_addresses>

# pass in traffic on internet ports
pass in on $ext_if proto { tcp, udp } from any to <iface_addresses> port $internet_ports flags S/SA keep state

# throttle ssh connection attempts and block their ip if a bruteforce attempt is detected
pass in quick on $ext_if proto tcp from any to any port ssh \
flags S/SA keep state \
(max-src-conn 15, max-src-conn-rate 5/3, \
overload <bruteforce> flush global)

# allow traffic from interface addresses to localhost
pass out quick on $ext_if from <interfaces_addresses> to 127.0.0.1

# allow local network admin ip addresses
pass in on $ext_if proto { tcp, udp } from $local_networks to $ext_if

# keep state on outbound connections made from one of the ip addresses on interface
pass out on $ext_if proto tcp from any to any flags S/SA modulate state
pass out on $ext_if proto { udp, icmp } from any to any keep state


 Apache Configuration

# /usr/local/etc/apache22/httpd.conf
# ----------------------------------


Listen X.X.X.Y:80 # Default
Listen X.X.X.Z:80 # VHost
Listen X.X.X.Z:80:443 # VHost

HTTP Virtual Hosts

# /usr/local/etc/apache22/Includes/httpd-vhosts.conf
# --------------------------------------------------
NameVirtualHost X.X.X.Z:80

<VirtualHost X.X.X.Z:80>
ServerName DOMAIN.com
ServerAlias www.DOMAIN.com
ServerAdmin info@DOMAIN.com
ServerSignature On
RequestHeader set Front-End-Https "On"
ProxyRequests Off
ProxyPreserveHost On

ErrorLog "/var/log/DOMAIN-error_log"
CustomLog "/var/log/DOMAIN-access_log" common
LogLevel warn

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteLogLevel 2
RewriteRule ^/icons/ - [L]
RewriteRule ^/(.*)/manage(.*) \
https://DOMAIN.com/$1/manage$2 [NC,R=301,L]
RewriteRule ^/manage(.*) \
https://DOMAIN.com/manage$1 [NC,R=301,L]
RewriteRule ^/login_(.*) https://%{SERVER_NAME}/login_$1 [NE,L]
RewriteRule ^/(.*) \
http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/$1 [P,L]
</IfModule>
<IfModule mod_proxy.c>
ProxyVia On
ProxyPass / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
ProxyPassReverse / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
<ProxyMatch http://127.0.0.1:*/.* >
Order deny,allow
Deny from all
Allow from X.X.X.Y
</ProxyMatch>
<LocationMatch "^[^/]">
Deny from all
</LocationMatch>
</IfModule>
</VirtualHost>

SSL Virtual Hosts

# /usr/local/etc/apache22/Includes/httpd-ssl.conf

NameVirtualHost X.X.X.Z:443

<VirtualHost X.X.X.Z:443>
DocumentRoot "/usr/local/www/apache22/data"
ServerName DOMAIN.com
ServerAdmin info@DOMAIN.com
ErrorLog "/var/log/DOMAIN-ssl-error.log"
TransferLog "/var/log/DOMAIN-ssl-access.log"

SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+SSLv3:+EXP:+eNULL
SSLCertificateFile "/usr/local/etc/apache22/ssl.crt/DOMAIN.com.crt"
SSLCertificateKeyFile "/usr/local/etc/apache22/ssl.key/DOMAIN.com.key"

<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "/usr/local/www/apache22/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0

CustomLog "/var/log/cfhinton-ssl_request.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteLogLevel 2

RewriteRule ^/(.*) \
http://127.0.0.1:8902/VirtualHostBase/https/%{SERVER_NAME}:443/MyPloneSite/VirtualHostRoot/$1 [L,P]
</IfModule>
<IfModule mod_proxy.c>
ProxyVia On
ProxyPass / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
ProxyPassReverse / http://127.0.0.1:8902/VirtualHostBase/http/%{SERVER_NAME}:80/MyPloneSite/VirtualHostRoot/
<ProxyMatch http://127.0.0.1:*/.* >
Order deny,allow
Deny from all
Allow from X.X.X.Y
</ProxyMatch>
<LocationMatch "^[^/]">
Deny from all
</LocationMatch>
</IfModule>
</VirtualHost>

SSH Tunnel (access ZMI via http://localhost:9999

ssh -f user@mydomain.com -L 9999:localhost:8095 -N 
 

Tuesday, December 30, 2008

Building PHP5 on Linux

 ./configure options for PHP 5.2.6 Build on Linux running 2.6.18-92 Kernel

# ./configure --disable-static --disable-debug  --prefix=/usr/local/apache2/php --with-config-file-scan-dir=/usr/local/apache2/php --enable-libxml  --with-libxml-dir=/usr/local/lib  --enable-reflection --enable-spl --enable-zend-multibyte --with-regex=system  --with-tidy  --enable-zip --enable-bcmath --with-bz2=shared --enable-calendar --with-curl=shared --enable-dba --enable-exif --enable-ftp --with-gd --enable-gd-native-ttf --with-jpeg-dir=/usr --with-png-dir=/usr --with-zlib-dir=/usr --with-gettext=shared  --with-gmp=shared --with-imap-ssl --with-imap --enable-mbstring --with-mcrypt=shared --with-mhash=shared --with-mysql --with-mysqli --with-openssl-dir --with-pdo-mysql --enable-sockets --with-xsl --with-zlib --with-apxs2=/usr/local/apache2/bin/apxs --disable-cgi --enable-pcntl --enable-soap --enable-dbase --enable-sysvmsg --enable-sysvsem --enable-sysvshm   --with-zlib  --with-gdbm  --with-curl --enable-soap --with-kerberos

 # make && make install

# chown -R apache.web /usr/local/apache2/

Tuesday, March 11, 2008

Libpq vs Libpqxx

Libpq is the C application programmer's interface to PostgreSQL, and Libpqxx is the C++ application programmer's interface to PostgreSQL. Libpqxx actually wraps the functions in Libpq. However, Libpqxx is slower than Libpq, and Libpqxx 2.6.9 is not compatible with PostgreSQL 8.3 and GCC 4.1.x on Red Hat / Fedora 5.

After using Libpqxx for the past 5 years on a PostgreSQL 7.4 database, I migrated the database to 8.3 and Libpqxx to the current stable version - 2.6.9. I am running dual quad-core Xeon processors on a 64-bit Red Hat Enterprise 5 Server with GCC 4.1.x. Libpqxx is just a wrapper library around Libpq. There are performance issues because Libpq can be called directly without incurring object / template overhead. After deciding to migrate our codebase to use Libpq, I was very pleased with the results. Error checking is simple, code execution is faster, and library / executable sizes were reduced.

Monday, December 3, 2007

RESTful Web Services

After writing a simple Ruby interface into Flickr this weekend, I began to question why Flickr wrote their API the way that they did. Having some level of familiarity with Rails scaffolds and CRUD actions and having somewhat kept up with the state of web services development, I swung by the bookstore and picked up a copy of RESTful Web Services, by Leonard Richardson & Sam Ruby.

This is an exceptional book. I highly recommend this book to anyone who is doing anything technical with the Web.

For a detailed discussion of Representational State Transfer, see Roy Fielding's PhD dissertation, "Architectural Styles and the Design of Network-based Software Architectures". Roy Fielding is co-founder of the Apache project and worked on the original http protocol.

Thursday, November 22, 2007

Ruby on Rails and Lighttpd(SSL) Installation

Ruby on Rails and Lighttpd(SSL) Installation

The goal of this document is to explain how to set up Ruby on Rails on Lighttpd with SSL enabled and MySQL running in the background. It will cover the proper configuration of the database, as well as how to configure Rails for sending emails. Finally, it will walk through a sample Rails application that uses partials to render a basic website template, with separate header, content, and footer sections.

I found it difficult to find all of this information in one place on the internet, so I hope that this document is helpful for anyone configuring a Rails development environment or building their first Rails application in a Linux environment.

Ruby is an interpreted, dynamically-typed, object-oriented programming language, while Rails is a web development framework that uses the Model-View-Controller software design pattern for building web applications. Rails applications are written in Ruby.

Lighttpd is a fast and lightweight web server. Ruby on Rails provides an excellent abstraction of the backend database, and in our case, we will be using MySQL as the backend database.

I. Check the system

Before installing, let's check that our system has the necessary tools so that the installation process can proceed smoothly. The system we'll be setting up should be similar to my own.
$ echo $SHELL
/bin/bash

$ uname -a
Linux dash.bryanhinton.com 2.6.18-8.1.10.el5 #1 SMP Thu Aug 30 20:43:15 EDT 2007 \
i686 i686 i386 GNU/Linux

$ echo $PATH
/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/bin:/bin: \
/usr/bin:/home/bryan/bin:/usr/local/bin:/usr/sbin

$ echo $LD_LIBRARY_PATH
/usr/local/lib:/usr/lib:/lib

$ make -v
GNU Make 3.81

$ autoconf -V
autoconf (GNU Autoconf) 2.59

$ gcc -v
Using built-in specs.
Target: i386-redhat-linux
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man --infodir=/usr/share/info \
--enable-shared --enable-threads=posix --enable-checking=release --with-system-zlib \
--enable-__cxa_atexit --disable-libunwind-exceptions \
--enable-libgcj-multifile --enable-languages=c,c++,objc,obj-c++,java,fortran,ada \
--enable-java-awt=gtk --disable-dssi --enable-plugin \
--with-java-home=/usr/lib/jvm/java-1.4.2-gcj-1.4.2.0/jre \
--with-cpu=generic --host=i386-redhat-linux
Thread model: posix
gcc version 4.1.1 20070105 (Red Hat 4.1.1-52)

II. Check the host configuration on the network

Change the hostname.

$ su
*******

# hostname
WCLI404892341

# hostname dash.bryanhinton.com

# hostname
dash.bryanhinton.com

Now Open /etc/sysconfig/network and /etc/hosts and make sure that they look like the following:

# cat /etc/sysconfig/network
NETWORKING=yes
NETWORKING_IPV6=yes
HOSTNAME=dash.bryanhinton.com

# cat /etc/hosts
127.0.0.1       localhost.localdomain localhost
74.53.242.146   dash.bryanhinton.com    dash
::1             localhost6.localdomain6 localhost6

III. Install Ruby 1.8.6 patchlevel 110, RubyGems 0.9.5, and Ruby FastCGI Bindings

As of November 24, 2007, 1.8.6-p110 is the recommended, stable version and 0.9.5 is the recommended, stable version of RubyGems. RubyGems is the Ruby package management system and a gem is a packaged Ruby application or library. 

# exit
$ mkdir $HOME/src
$ cd $HOME/src
$ wget http://ftp.ruby-lang.org/pub/ruby/1.8/ruby-1.8.6.tar.gz
$ tar -xzvf ruby-1.8.6.tar
$ cd ruby-1.8.6
$ ./configure
$ make
$ su
*******

# make install

# exit

$ which ruby
/usr/local/bin/ruby

$ ruby -v
ruby 1.8.6 (2007-09-23 patchlevel 110) [i686-linux]

$ cd $HOME/src

$ wget http://rubyforge.org/frs/download.php/28174/rubygems-0.9.5.tgz

$ tar -xzvf rubygems-0.9.5.tgz

$ cd rubygems-0.9.5

$ su
******

# ruby setup.rb

# exit

# gem -v
0.9.5

# gem install fcgi

IV. Install Rails

# gem install rails --include-dependencies

V. Install Lighttpd with SSL

# openssl version
OpenSSL 0.9.8b 04 May 2006

# exit

$ cd $HOME/src

$ wget http://www.lighttpd.net/download/lighttpd-1.4.18.tar.gz

$ tar -xzvf  lighttpd-1.4.18.tar.gz

$ cd lighttpd-1.4.18

$ ./configure --with-openssl --with-openssl-libs=/usr/lib/openssl
...
...
...
Plugins:

enabled:
  mod_access
  mod_accesslog
  mod_alias
  mod_auth
  mod_cgi
  mod_compress
  mod_dirlisting
  mod_evhost
  mod_expire
  mod_extforward
  mod_fastcgi
  mod_flv_streaming
  mod_indexfiles
  mod_proxy
  mod_redirect
  mod_rewrite
  mod_rrdtool
  mod_scgi
  mod_secdownload
  mod_setenv
  mod_simple_vhost
  mod_ssi
  mod_staticfile
  mod_status
  mod_trigger_b4_dl
  mod_userdir
  mod_usertrack
  mod_webdav
disabled:
  mod_cml
  mod_magnet
  mod_mysql_vhost

Features:

enabled:
  auth-crypt
  compress-bzip2
  compress-deflate
  compress-gzip
  large-files
  network-ipv6
  network-openssl
  regex-conditionals
disabled:
  auth-ldap
  stat-cache-fam
  storage-gdbm
  storage-memcache
  webdav-locks
  webdav-properties

$ make

$ su
******

# make install

# mkdir /etc/lighttpd/

# cp doc/lighttpd.conf /etc/lighttpd/

# cp doc/rc.lighttpd /etc/init.d/lighttpd

# chmod +x /etc/init.d/lighttpd

# mkdir /var/www

# mkdir /var/www/html

# groupadd lighttpd

# useradd -g lighttpd -d /var/www -s /bin/false lighttpd

# chown -R lighttpd.lighttpd /var/www

# chown -R lighttpd.lighttpd /var/log/lighttpd

Now let's Configure Lighttpd. As stated earlier, there is a public IP address bound to the network card. We are going to bind the lighttpd daemon to the public IP address on port 80 and port 443. This assumes that a correctly configured SSL certificate. The following lines in /etc/init.d/lighttpd.conf should look like the following:

server.username            = "lighttpd"
server.groupname           = "lighttpd"
accesslog.filename          = "/var/log/lighttpd/access.log"
$HTTP["host"] =~ "bryanhinton\.com$" {
  server.document-root = "/var/www/html/bryanhinton/public/"
  accesslog.filename = "/var/www/html/bryanhinton/log/access.log"
  server.indexfiles = ( "dispatch.fcgi", "index.html" )
  server.error-handler-404 = "/dispatch.fcgi"

  # rails stuff
  #### fastcgi module
  fastcgi.server = (
    ".fcgi" => (
      "test" => (
        "socket" => "/tmp/test1.socket",
        "bin-path" => "/var/www/html/bryanhinton/public/dispatch.fcgi",
        "min-procs" => 1,
        "max_procs" => 2
      )
    )
  )
}
$SERVER["socket"] == "74.53.242.146:443" {
  ssl.engine = "enable"
  ssl.pemfile = "/etc/lighttpd/ssl/bryanhinton.com/bryanhinton.pem"
  server.name = "bryanhinton.com"
  server.document-root = "/var/www/html/bryanhinton/public/"
}

VI. Start Lighttpd

# /etc/init.d/lighttpd start

VII. Configure a Rails Application

First, let's make sure our standard login ID is associated with the lighttpd group. Open /etc/groups and make sure that there is a line that looks like the following:

lighttpd:x:521:lighttpd,LOGIN_ID

Configure a Rails Application

$ cd /var/www/html

$ rails bryanhinton

$ cd bryanhinton

$ ruby script/generate controller Content

$ rm public/index.html

edit config/routes.rb

# add this to line 21
map.connect ':action', :controller => 'Content'


# original line 24
#map.connect '', :controller => "welcome" 

# change to this on line 24
map.connect '', :controller => 'Content'

Setup smtp to send e-mail from Rails. Modify config/environments/development.rb so that it looks like the following:

config.action_mailer.raise_delivery_errors = false
config.action_mailer.delivery_method = :smtp
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
config.action_mailer.smtp_settings = {
   :address => "smtphost.bryanhinton.com"
   :port => 25,
   :domain => "bryanhinton.com"
   :authentication => :log
   :user_name => "INSERT USERNAME HERE"
   :password => "INSERT PASSWORD HERE"
}

IIX. Create a development database in MySQL and then Configure in Rails

$ mysqladmin -u myusername create bryanhinton_development -p

$ gem install mysql

Edit config/database.yml and ensure that it looks similar to the following. We are only setting up a development database

development:
  adapter: mysql
  database: bryanhinton_development
  username: MY_MYSQL_USER_NAME
  password: MY_MYSQL_PASSWORD
  socket: /var/lib/mysql/mysql.sock

IX. Test the database connection

$ cd /var/www/html/bryanhinton
$ rake db:migrate

X. Create site layout

$ cd /var/www/html/bryanhinton/app/views/layouts

Place the following lines in application.rhtml

<html>
<body>
<%= render :partial => "layouts/header" %>
<%= render :partial => "layouts/leftnav" %>
<%= render :partial => "layouts/rightnav" %>
<%= yield :layout %>
<%= render :partial => "layouts/footer" %>
</body>
</html>

Create the files that application.rhtml references

$ echo "My Header" > _header.rhtml
$ echo "Left Menu" > _leftnav.rhtml
$ echo "Right Col News" > _rightnav.rhtml
$ echo "My Footer" > _footer.rhtml

XI. Create an index method in the Content controller

Place the following lines in /var/www/html/bryanhinton/app/controllers/content_controller.rb

class ContentController < ApplicationController
def index
end

XII. Create a view for the index method

Create a view for the index method called index.rhtml in /var/www/html/bryanhinton/app/views/content

$ cd /var/www/html/bryanhinton/app/views/content

$ echo "Hello World!" > index.rhtml

XIII. Test the installation!

Open up a web browser and go to the site URL i.e. http://bryanhinton.com OR http://bryanhinton.com/index

Wednesday, January 3, 2001

OpenBSD bridge without IPs using IPF Tutorial

This document was originally published in Daemon News on May 21, 2003.

Hogan, Doug and Hinton, Bryan. “OpenBSD bridge without IPs using IPF tutorial.” March 2001. URL: http://www.daemonnews.org/200103/ipf_bridge.html . (21 May 2003)
See references at the end of https://www.giac.org/paper/gsec/3060/openbsd-invisible-firewall/105092


With OpenBSD and IP Filter, a bridge can be setup that filters incoming traffic. The bridge is not assigned an IP address on either network card. The benefit of this type of firewall is that the sender of an incoming packet is entirely oblivious to the existence of an intermediate bridge. This provides transparency and allows the firewall, which is maintained on the bridge, to securely filter incoming packets and forward them without modification to the internal destination. This guide walks through two typical home network connection setups (ADSL and cable modem) using OpenBSD 2.8.

Overview

With OpenBSD and IP Filter, a bridge can be setup that filters incoming traffic. The bridge is not assigned an IP address on either network card. The benefit of this type of firewall is that the sender of an incoming packet is entirely oblivious to the existence of an intermediate bridge. This provides transparency and allows the firewall, which is maintained on the bridge, to securely filter incoming packets and forward them without modification to the internal destination. This guide walks through two typical home network connection setups (ADSL and cable modem) using OpenBSD 2.8.

A bridge is a software or hardware device used to connect two network segments. Unlike a router, it creates the appearance of a single, large network segment. The bridge used in this example will be transparent. It will not allow any connections to be made to its internal services and it will still function as a secure firewall and stateful packet filter.

These examples are "real world" examples of two typical network environments.

Example 1 - An ADSL line connected via a hardware router, with all LAN workstations using static IPs and running services.

Example 2 - A cable modem Internet connection with all LAN workstations reaching the Internet through a single, separate router computer. Nat cannot be run on the bridge because the bridge does not have ip addresses assigned to it's interfaces. No services will be run on the LAN workstations.

 


Setup Overview

The first step is to setup configuration files so that the bridge will be activated upon reboot. These files must be configured for the bridge to properly function:

  1. Edit /etc/hostname.*

      /etc/hostname. must be setup for each network card. These files are used when the system boots. If these files exist, the initialization scripts take the information contained in these files and configure the devices.
      Use 'dmesg' as a guide to what network card driver is being used.

  2. Edit /etc/bridgename.bridge0

      /etc/bridgename.bridge0 needs to be created so that the bridge will be brought up during system initialization.

  3. Edit /etc/ipf.rules

      /etc/ipf.rules must be created for the packet filtering rules to take place.

  4. Edit /etc/rc.conf

      /etc/rc.conf must be edited to turn on IPF (IP Filter).
      rc.conf must have "ipfilter=YES"


Example 1: ADSL line with services on static IPs

Network topology:

adsl <--> hw router with 4 ports <--> /fxp0 bridge /fxp1 <--> 5port 3 com hub <---> Internal LAN computers

The Internet connection, an ADSL line, enters the hardware router. An rj45 cable connects the hardware router and the bridge. This connects to interface fxp0 on the bridge. The bridge's second network card, fxp1, connects to the 5 port hub through another rj45 cable. Using static ip addresses, the LAN workstations connect, through the hub, to the internet.

    Hardware Used:
  • Hardware router

  • Bridge computer
        Workstation running OpenBSD 2.8
        Intel pro/100 network card with device name: fxp0
        Intel pro/100 network card with device name: fxp1

  • 5 port 3com home connect hub

  • Enough RJ-45 cable for the network

fxp0 is the external network interface and is connected to the Internet through the hardware ADSL router.
fxp1 is the internal network interface and is connected to the LAN hub.

Changes to /etc/rc.conf

ipfilter=YES                 # IPF must be enabled for the bridge to work
inetd=NO # Services will not be run on this box
portmap=NO # No reason to have this enabled

Create /etc/hostname.fxp0

inet media 10BaseT           # Adjust this to the proper media type 
up # See ifconfig(8) for more details

Create /etc/hostname.fxp1

inet media 10BaseT           # Also adjust to proper network media type
up

Create /etc/bridgename.bridge0

add fxp0 add fxp1 up

Create /etc/ipf.rules

#------------------------------------------------------------------
# fxp0 - External interface - internet
# fxp1 - Internal interface - protected
# lo0 - loopback interface - localhost only
# Netmask = 255.255.255.248 = /29
# 1.1.1.9 Web Server, Primary DNS, Mail Server
# 1.1.1.8 Secondary DNS
# 1.1.1.7 Workstation

#
# Allow all incoming and outgoing packets on the internal loopback interface
#

pass in quick on lo0 all
pass out quick on lo0 all

#
# drop any IP packets with options set
# ipopts include lsrr and ssrr
# IPF example ipopts
#

block in quick all with ipopts

#
# Drop any packets that are too short to compare
# IPF examples short
#

block in quick all with short

#
# Block any incoming IP fragments
# IPF examples

block in quick all with frag

pass in quick on fxp1 proto tcp/udp all keep state
pass in quick on fxp1 proto icmp all keep state

#
# Don't allow any other incoming traffic to the internal network card.
#

block in quick on fxp1 all

#
# Block nmap OS fingerprinting attempts
# From the OpenBSD FAQ.
#

block in quick on fxp0 proto tcp all flags FUP

#
# Block incoming traffic from the unroutable address blocks
#
# See http://www.3com.com/nsc/501302.html for more info on unroutables.
#
# Note: 'out' cannot be used with any of these bridge rules. Therefore,
# block in on the other interface. It will probably stay that
# way as it's harder to allow 'out' rules.
#
# Blocking in on fxp0 will keep inappropriate IPs off of the external interface.
# Blocking in on fxp1 will keep inappropriate packets from coming out
# of the internal network.
#

block in quick on fxp0 from 255.255.255.255/32 to any
block in quick on fxp0 from 192.168.0.0/16 to any
block in quick on fxp0 from 172.16.0.0/12 to any
block in quick on fxp0 from 127.0.0.0/8 to any
block in quick on fxp0 from 10.0.0.0/8 to any
block in quick on fxp0 from 0.0.0.0/32 to any

#
# Prevent smurf attack
# To prevent this, incoming traffic in the broadcast address range needs to be
# blocked.
# Directed broadcasts are off by default OpenBSD FAQ 6.6
#

block in log quick on fxp0 from any to 1.1.1.0/29
block in log quick on fxp0 from any to 1.1.1.255/29

#
# Protect real IP addresses behind the firewall
#

block in log quick on fxp0 from 1.1.1.7 to any
block in log quick on fxp0 from 1.1.1.8 to any
block in log quick on fxp0 from 1.1.1.9 to any

#
# Pass in and keep state on certain types of ICMP messages.
# Allow ICMP messages that are non-volatile and needed because of added
# functionality:
# icmp-type 0 : echo reply (ping reply) RFC 792
# icmp-type 3 : Destination Unreachable RFC 792
# icmp-type 8 : echo request (ping request) RFC 792
# icmp-type 11: time exceeded (traceroute) RFC 792
# Larger list of ICMP type numbers
#

pass in quick on fxp0 proto icmp from any to 1.1.1.9/29 icmp-type 0 keep state
pass in quick on fxp0 proto icmp from any to 1.1.1.9/29 icmp-type 3 keep state
pass in quick on fxp0 proto icmp from any to 1.1.1.9/29 icmp-type 8 keep state
pass in quick on fxp0 proto icmp from any to 1.1.1.9/29 icmp-type 11 keep state

#
# DNS generally uses TCP under two circumstances.
# 1. Zone transfers between primary and secondary name servers.
# 2. When a client make a query (udp) and the response exceeds 512 bytes, the query is re-issued using tcp.
# Thus, allow TCP on port 53 but keep state and check for the Syn flag (tcp).
#
# See section 2.7 (page 11) and 3.3 (page 25) of RFC 793
# and IPF example tcpflags for more information on 'flags S'.
#

pass in quick on fxp0 proto tcp from any to 1.1.1.8 port = 53 flags S keep state
pass in quick on fxp0 proto tcp from any to 1.1.1.9 port = 53 flags S keep state

#
# Allow people to query my nameservers but keep state (udp) on the connection
# See RFC 1034 section 4.3.5 for more information on DNS.
#

pass in quick on fxp0 proto udp from any to 1.1.1.8 port = 53 keep state
pass in quick on fxp0 proto udp from any to 1.1.1.9 port = 53 keep state

#
# Mail (SMTP) - allow packets with only syn flag set (initial connection) and
# keep state on connection.
# See section 2.7 (page 11) and 3.3 (page 25) of RFC 793
# and IPF example tcpflags for more information.
#

pass in quick on fxp0 proto tcp from any to 1.1.1.9 port = 25 flags S keep state

#
# Webserver - allow packets with only syn flag set (set during initial
# connection) and keep state on connection.
# See section 2.7 (page 11) and 3.3 (page 25) of RFC 793
# and IPF example tcpflags for more information.
#

pass in quick on fxp0 proto tcp from any to any port = 80  flags S keep state

#
# Block any other incoming traffic
#

block in quick on fxp0

Example 2: Cable modem with software router running NAT and no services

Internet --- cable modem ----- /ep0 bridge /ep1 --- /xl0 software router /xl1 ----- 8 port hub --- Internal LAN computers

The cable modem is the connection to the outside network, the Internet. The cable modem is connected to the first network card, xl0, on the bridge. From there, packets are checked using IPF and, if they pass, they are sent to the second network card, xl1, and used by the internal network. The xl1 interface is connected to the first network card on the OpenBSD software router using RJ-45 cable. From here the traffic is again analyzed but, this time, by IP Network Address Translation (IPNAT). Subsequently, IPNAT forwards the packets to the correct host in the internal network. From the second network card, ep1, the packets which pass are sent to the 8 port hub. Here, the packets are broadcast to all of the LAN computers.

    Hardware Used:

     

  • cable modem

  •     Bridge computer
        OpenBSD workstation running 2.8
        3com 3c905b-TX network card with device name: ep0
        3com 3c905b-TX network card with device name: ep1

  •     Router computer running NAT
        OpenBSD workstation running 2.8
        3com 3c509 network card with device name: xl0
        3com 3c509 network card with device name: xl1

  • 8 port hub.

  • Enough RJ-45 cable for the network.

  • RJ-45 crossover cable for going between the bridge and router.

ep0 is the network card connected to the cable modem
ep1 is the network card connected to the internal network.

Changes to /etc/rc.conf

ipfilter=YES                 # enable IPF for the bridge to work
inetd=NO # services cannot be run on this box anyway
portmap=NO # No reason to have this enabled

Create /etc/hostname.ep0

media 10BaseT up

Create /etc/hostname.ep1

media 10BaseT up

Create /etc/bridgename.bridge0

add ep0
add ep1
up

Create /etc/ipf.rules

#-----------------------------------
# ep0 - Network card connected to the cable modem through rj-45
# ep1 - Network card connected to the Internal router - protected
# lo0 - loopback, localhost only
#
# Allow the loopback device to bypass the rules since it is localhost.
#

pass in quick on lo0 all

#
# drop any packets with IP options set
# IPopts include lsrr and ssrr
# IPF example ipopts
#

block  in quick all with ipopts

#
# Drop any packets that are too short to compare
# A short packet doesn't contain a complete IP header
# IPF example short
#

block  in quick all with short

#
# Block any incoming IP fragments
# A frag is a fragment of an IP datagram
# IPF example frag
#

block in quick all with frag

#
# Block nmap OS fingerprinting attempts
# From the OpenBSD FAQ.
#

     block  in quick proto tcp all flags FUP

#
# Pass in packets from DHCP server
# May not be needed in all cases if the dhcp lease lasts a long time.
# This assumes that the ISP's DHCP server is 24.168.0.1; change it accordingly.
# If unknown, dhcp client will use 0.0.0.0/32 with a broadcast
# address of 255.255.255.255/32 so change this line.
#

pass in quick on ep0 proto udp from 24.168.0.1/32 port = 67 to any port = 68 keep state

#
# Block incoming traffic from the unroutable address blocks
# See http://www.3com.com/nsc/501302.html for more info on unroutable
#

block in quick on ep0 from 192.168.0.0/16 to any
block in quick on ep0 from 172.16.0.0/12 to any
block in quick on ep0 from 127.0.0.0/8 to any
block in quick on ep0 from 10.0.0.0/8 to any

#
# add in blocks on ep1 from LAN IPs other than the class being
# used. Try to keep it as generic as possible.
#

#
# Allow packets out and keep state on them. This allows use of
# the connection as if there was no firewall, but outside users
# cannot connect to. If the packets passed the rules above (were not
# matched) then these packets will be allowed to leave the internal
# network and proceed on to the Internet by these two rules.
#
# See section 2.7 (page 11) and 3.3 (page 25) of RFC 793
# and IPF example tcpflags for more information on 'flags S'.
#

pass  in quick on ep1 proto tcp from any to any flags S keep state
pass in quick on ep1 proto udp from any to any keep state
pass in quick on ep1 proto icmp from any to any keep state

#
# Do not allow any traffic coming in that has not not initiated first
# since there are not any servers running. The keep state rules for ep1
# above will let the packets out. And this rule doesn't allow anyone
# to contact the computer.
#

block in quick all

Manually initialize interfaces

Rather than rebooting the computer to clear and re-initialize the network interfaces, the following commands may be executed with super-user privelages if ipf has already been activated in the kernel.

root@localhost# ifconfig fxp0 delete
root@localhost# ifconfig fxp1 delete
root@localhost# brconfig bridge0 add fxp0 add fxp1 up

If the bridge0 interface was up from another configuration, flush the interface cache and delete all existing interfaces from bridge0.

root@localhost# brconfig bridge0 flushall 
root@localhost# brconfig bridge delete fxp0
root@localhost# brconfig bridge delete fxp1
root@localhost# brconfig bridge0 add fxp0 add fxp1 up

Make sure all of the interfaces are up and configured correctly. The network interface parameters should look like the following. Run the following commands to verify.

root@localhost# ifconfig fxp0
fxp0: flags=8943 mtu 1500
media: Ethernet autoselect (10BaseT)
status: active
root@localhost# ifconfig fxp1
fxp1: flags=8943 mtu 1500
media: Ethernet autoselect (10BaseT)
status: active
root@localhost# ifconfig bridge0
bridge0: flags=41 mtu 1500

In addition, run the following command to verify bridge0's configuration.
Note: xx:xx:xx:xx:xx:xx is some arbitrary hex address.

root@localhost# brconfig bridge0
bridge0: flags=41
Interfaces:
fxp1 flags=3
fxp0 flags=3
Addresses( max cache: 100, timeout: 240):
xx:xx:xx:xx:xx:xx fxp1 1 flags=0<>
xx:xx:xx:xx:xx:xx fxp0 1 flags=0<>
xx:xx:xx:xx:xx:xx fxp0 1 flags=0<>

Initialize IPF

Run the following command to initialize the ruleset if not rebooting.

root@localhost# ipf -Fa -FS -vf /etc/ipf.rules -E

Configure LAN Workstations

The firewall/bridge is now transparent. Individual LAN workstations and or servers may be configured using the route command. For example, if the isp assigned the gateway address: 1.1.1.10, the following could be used to set up the route on an individual workstation.

root@localhost# route add default 1.1.1.10

References

  1. brconfig(8) man page html ascii

  2. bridge(4) man page html ascii

  3. hostname.if(5) and bridgename.if(5) man page html ascii

  4. ipf(5) rules syntax man page html ascii

  5. ipf(8) command man page html ascii

  6. ipfstat(8) (filter statistics) html ascii

  7. OpenBSD FAQ on IP Filter

  8. IP Filter website

  9. IP Filter examples

  10. IP Filter mailing list

  11. IP Filter howto html text postscript Adobe Acrobat

  12. IPF Stateful filtering postscript

  13. Building Linux and OpenBSD Firewalls,   Wes SonnenReich, Tom Yates (John Wiley & Sons, 2000)

  14. TCP/IP Illustrated, Volume 1: The Protocols,   W. Richard Stevens (Prentice Hall, 1994)

  15. Practical Internetworking with TCP/IP and UNIX,   Smoot Carl-Mitchell, John S. Quarterman (Addison-Wesley, 1993)


About us

Bryan Hinton is an undergraduate student at the University of Texas at Dallas majoring in computer science.  He is concurrently working on his undergraduate and graduate degrees in Computer Science.

Doug Hogan  is an undergraduate student at the University of Cincinnati majoring in computer science. He is the vice-president of the UC Free Operating Systems group. Doug is a member of the OpenBSD development team.